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;
 
  165 import org.
sleuthkit.datamodel.TskUnsupportedSchemaVersionException;
 
  192             = Executors.newSingleThreadExecutor(
new ThreadFactoryBuilder().setNameFormat(
"case-open-file-systems-%d").build());
 
  212         WindowManager.getDefault().invokeWhenUIReady(() -> {
 
  213             mainFrame = WindowManager.getDefault().getMainWindow();
 
  235             if (typeName != null) {
 
  237                     if (typeName.equalsIgnoreCase(c.toString())) {
 
  261             "Case_caseType_singleUser=Single-user case",
 
  262             "Case_caseType_multiUser=Multi-user case" 
  265             if (fromString(typeName) == SINGLE_USER_CASE) {
 
  266                 return Bundle.Case_caseType_singleUser();
 
  268                 return Bundle.Case_caseType_multiUser();
 
  278             this.typeName = typeName;
 
  293             return (otherTypeName == null) ? 
false : typeName.equals(otherTypeName);
 
  548             } 
catch (TskCoreException ex) {
 
  549                 logger.log(Level.SEVERE, 
"Unable to retrieve the hasData status from the db", ex);
 
  592             } 
catch (TskCoreException ex) {
 
  593                 logger.log(Level.SEVERE, 
"Unable to retrieve the hasData status from the db", ex);
 
  676                 .map(Events::toString)
 
  677                 .collect(Collectors.toSet()), listener);
 
  688                 .map(Events::toString)
 
  689                 .collect(Collectors.toSet()), listener);
 
  712         eventTypes.forEach((
Events event) -> {
 
  757         eventTypes.forEach((
Events event) -> {
 
  771         return !(caseName.contains(
"\\") || caseName.contains(
"/") || caseName.contains(
":")
 
  772                 || caseName.contains(
"*") || caseName.contains(
"?") || caseName.contains(
"\"")
 
  773                 || caseName.contains(
"<") || caseName.contains(
">") || caseName.contains(
"|"));
 
  825         "Case.exceptionMessage.emptyCaseName=Must specify a case name.",
 
  826         "Case.exceptionMessage.emptyCaseDir=Must specify a case directory path." 
  830             throw new CaseActionException(Bundle.Case_exceptionMessage_emptyCaseName());
 
  832         if (caseDir.isEmpty()) {
 
  833             throw new CaseActionException(Bundle.Case_exceptionMessage_emptyCaseDir());
 
  852         "# {0} - exception message", 
"Case.exceptionMessage.failedToReadMetadata=Failed to read case metadata:\n{0}.",
 
  853         "Case.exceptionMessage.cannotOpenMultiUserCaseNoSettings=Multi-user settings are missing (see Tools, Options, Multi-user tab), cannot open a multi-user case." 
  858             metadata = 
new CaseMetadata(Paths.get(caseMetadataFilePath));
 
  860             throw new CaseActionException(Bundle.Case_exceptionMessage_failedToReadMetadata(ex.getLocalizedMessage()), ex);
 
  863             throw new CaseActionException(Bundle.Case_exceptionMessage_cannotOpenMultiUserCaseNoSettings());
 
  874         return currentCase != null;
 
  891             throw new IllegalStateException(NbBundle.getMessage(
Case.class, 
"Case.getCurCase.exception.noneOpen"), ex);
 
  915         if (openCase == null) {
 
  916             throw new NoCurrentCaseException(NbBundle.getMessage(
Case.class, 
"Case.getCurCase.exception.noneOpen"));
 
  931         "# {0} - exception message", 
"Case.closeException.couldNotCloseCase=Error closing case: {0}",
 
  932         "Case.progressIndicatorTitle.closingCase=Closing Case" 
  936             if (null == currentCase) {
 
  942                 logger.log(Level.INFO, 
"Closing current case {0} ({1}) in {2}", 
new Object[]{closedCase.getDisplayName(), closedCase.getName(), closedCase.getCaseDirectory()}); 
 
  944                 logger.log(Level.INFO, 
"Closed current case {0} ({1}) in {2}", 
new Object[]{closedCase.getDisplayName(), closedCase.getName(), closedCase.getCaseDirectory()}); 
 
  945             } 
catch (CaseActionException ex) {
 
  967             if (null == currentCase) {
 
  987         "Case.progressIndicatorTitle.deletingDataSource=Removing Data Source" 
  989     static void deleteDataSourceFromCurrentCase(Long dataSourceObjectID) 
throws CaseActionException {
 
  991             if (null == currentCase) {
 
  998             CaseMetadata caseMetadata = currentCase.
getMetadata();
 
 1006             Case theCase = 
new Case(caseMetadata);
 
 1007             theCase.doOpenCaseAction(Bundle.Case_progressIndicatorTitle_deletingDataSource(), theCase::deleteDataSource, CaseLockType.EXCLUSIVE, 
false, dataSourceObjectID);
 
 1028         "Case.progressIndicatorTitle.deletingCase=Deleting Case",
 
 1029         "Case.exceptionMessage.cannotDeleteCurrentCase=Cannot delete current case, it must be closed first.",
 
 1030         "# {0} - case display name", 
"Case.exceptionMessage.deletionInterrupted=Deletion of the case {0} was cancelled." 
 1034             if (null != currentCase) {
 
 1035                 throw new CaseActionException(Bundle.Case_exceptionMessage_cannotDeleteCurrentCase());
 
 1045         progressIndicator.
start(Bundle.Case_progressMessage_preparing());
 
 1052                 } 
catch (InterruptedException ex) {
 
 1058                     throw new CaseActionException(Bundle.Case_exceptionMessage_deletionInterrupted(metadata.
getCaseDisplayName()), ex);
 
 1062             progressIndicator.
finish();
 
 1077         "Case.progressIndicatorTitle.creatingCase=Creating Case",
 
 1078         "Case.progressIndicatorTitle.openingCase=Opening Case",
 
 1079         "Case.exceptionMessage.cannotLocateMainWindow=Cannot locate main application window" 
 1083             if (null != currentCase) {
 
 1086                 } 
catch (CaseActionException ex) {
 
 1095                 logger.log(Level.INFO, 
"Opening {0} ({1}) in {2} as the current case", 
new Object[]{newCurrentCase.getDisplayName(), newCurrentCase.getName(), newCurrentCase.getCaseDirectory()}); 
 
 1096                 String progressIndicatorTitle;
 
 1099                     progressIndicatorTitle = Bundle.Case_progressIndicatorTitle_creatingCase();
 
 1100                     openCaseAction = newCurrentCase::create;
 
 1102                     progressIndicatorTitle = Bundle.Case_progressIndicatorTitle_openingCase();
 
 1103                     openCaseAction = newCurrentCase::open;
 
 1106                 currentCase = newCurrentCase;
 
 1107                 logger.log(Level.INFO, 
"Opened {0} ({1}) in {2} as the current case", 
new Object[]{newCurrentCase.getDisplayName(), newCurrentCase.getName(), newCurrentCase.getCaseDirectory()}); 
 
 1113                 logger.log(Level.INFO, String.format(
"Cancelled opening %s (%s) in %s as the current case", newCurrentCase.
getDisplayName(), newCurrentCase.
getName(), newCurrentCase.
getCaseDirectory())); 
 
 1115             } 
catch (CaseActionException ex) {
 
 1116                 logger.log(Level.SEVERE, String.format(
"Error opening %s (%s) in %s as the current case", newCurrentCase.
getDisplayName(), newCurrentCase.
getName(), newCurrentCase.
getCaseDirectory()), ex); 
 
 1134         String uniqueCaseName = caseDisplayName.replaceAll(
"[^\\p{ASCII}]", 
"_"); 
 
 1139         uniqueCaseName = uniqueCaseName.replaceAll(
"[\\p{Cntrl}]", 
"_"); 
 
 1144         uniqueCaseName = uniqueCaseName.replaceAll(
"[ /?:'\"\\\\]", 
"_"); 
 
 1149         uniqueCaseName = uniqueCaseName.toLowerCase();
 
 1154         SimpleDateFormat dateFormat = 
new SimpleDateFormat(
"yyyyMMdd_HHmmss");
 
 1155         Date date = 
new Date();
 
 1156         uniqueCaseName = uniqueCaseName + 
"_" + dateFormat.format(date);
 
 1158         return uniqueCaseName;
 
 1175         File caseDir = 
new File(caseDirPath);
 
 1176         if (caseDir.exists()) {
 
 1177             if (caseDir.isFile()) {
 
 1178                 throw new CaseActionException(NbBundle.getMessage(
Case.class, 
"Case.createCaseDir.exception.existNotDir", caseDirPath));
 
 1179             } 
else if (!caseDir.canRead() || !caseDir.canWrite()) {
 
 1180                 throw new CaseActionException(NbBundle.getMessage(
Case.class, 
"Case.createCaseDir.exception.existCantRW", caseDirPath));
 
 1187         if (!caseDir.mkdirs()) {
 
 1188             throw new CaseActionException(NbBundle.getMessage(
Case.class, 
"Case.createCaseDir.exception.cantCreate", caseDirPath));
 
 1196         String hostPathComponent = 
"";
 
 1201         Path exportDir = Paths.get(caseDirPath, hostPathComponent, EXPORT_FOLDER);
 
 1202         if (!exportDir.toFile().mkdirs()) {
 
 1203             throw new CaseActionException(NbBundle.getMessage(
Case.class, 
"Case.createCaseDir.exception.cantCreateCaseDir", exportDir));
 
 1206         Path logsDir = Paths.get(caseDirPath, hostPathComponent, LOG_FOLDER);
 
 1207         if (!logsDir.toFile().mkdirs()) {
 
 1208             throw new CaseActionException(NbBundle.getMessage(
Case.class, 
"Case.createCaseDir.exception.cantCreateCaseDir", logsDir));
 
 1211         Path cacheDir = Paths.get(caseDirPath, hostPathComponent, CACHE_FOLDER);
 
 1212         if (!cacheDir.toFile().mkdirs()) {
 
 1213             throw new CaseActionException(NbBundle.getMessage(
Case.class, 
"Case.createCaseDir.exception.cantCreateCaseDir", cacheDir));
 
 1216         Path moduleOutputDir = Paths.get(caseDirPath, hostPathComponent, MODULE_FOLDER);
 
 1217         if (!moduleOutputDir.toFile().mkdirs()) {
 
 1218             throw new CaseActionException(NbBundle.getMessage(
Case.class, 
"Case.createCaseDir.exception.cantCreateModDir", moduleOutputDir));
 
 1221         Path reportsDir = Paths.get(caseDirPath, hostPathComponent, REPORTS_FOLDER);
 
 1222         if (!reportsDir.toFile().mkdirs()) {
 
 1223             throw new CaseActionException(NbBundle.getMessage(
Case.class, 
"Case.createCaseDir.exception.cantCreateReportsDir", reportsDir));
 
 1234     static Map<Long, String> getImagePaths(SleuthkitCase db) {
 
 1235         Map<Long, String> imgPaths = 
new HashMap<>();
 
 1237             Map<Long, List<String>> imgPathsList = db.getImagePaths();
 
 1238             for (Map.Entry<Long, List<String>> entry : imgPathsList.entrySet()) {
 
 1239                 if (entry.getValue().size() > 0) {
 
 1240                     imgPaths.put(entry.getKey(), entry.getValue().get(0));
 
 1243         } 
catch (TskCoreException ex) {
 
 1244             logger.log(Level.SEVERE, 
"Error getting image paths", ex); 
 
 1260         "Case.creationException.couldNotAcquireResourcesLock=Failed to get lock on case resources" 
 1264             Path caseDirPath = Paths.get(caseDir);
 
 1268         } 
catch (InterruptedException ex) {
 
 1271             throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock(), ex);
 
 1294         String backupDbPath = caseDb.getBackupDatabasePath();
 
 1295         if (null != backupDbPath) {
 
 1296             JOptionPane.showMessageDialog(
 
 1298                     NbBundle.getMessage(
Case.class, 
"Case.open.msgDlg.updated.msg", backupDbPath),
 
 1299                     NbBundle.getMessage(
Case.class, 
"Case.open.msgDlg.updated.title"),
 
 1300                     JOptionPane.INFORMATION_MESSAGE);
 
 1307         Map<Long, String> imgPaths = getImagePaths(caseDb);
 
 1308         for (Map.Entry<Long, String> entry : imgPaths.entrySet()) {
 
 1309             long obj_id = entry.getKey();
 
 1310             String path = entry.getValue();
 
 1318                     SwingUtilities.invokeAndWait(
new Runnable() {
 
 1321                             int response = JOptionPane.showConfirmDialog(
 
 1323                                     NbBundle.getMessage(
Case.class, 
"Case.checkImgExist.confDlg.doesntExist.msg", path),
 
 1324                                     NbBundle.getMessage(
Case.class, 
"Case.checkImgExist.confDlg.doesntExist.title"),
 
 1325                                     JOptionPane.YES_NO_OPTION);
 
 1326                             if (response == JOptionPane.YES_OPTION) {
 
 1327                                 MissingImageDialog.makeDialog(obj_id, caseDb);
 
 1329                                 logger.log(Level.SEVERE, 
"User proceeding with missing image files"); 
 
 1335                 } 
catch (InterruptedException | InvocationTargetException ex) {
 
 1336                     logger.log(Level.SEVERE, 
"Failed to show missing image confirmation dialog", ex); 
 
 1347         CallableSystemAction.get(CaseDetailsAction.class).setEnabled(
true);
 
 1362         final boolean hasData = newCurrentCase.
hasData();
 
 1364         SwingUtilities.invokeLater(() -> {
 
 1373             mainFrame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
 1380             mainFrame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
 
 1396             SwingUtilities.invokeLater(() -> {
 
 1406                 CallableSystemAction.get(
AddImageAction.class).setEnabled(
false);
 
 1409                 CallableSystemAction.get(CaseDetailsAction.class).setEnabled(
false);
 
 1411                 CallableSystemAction.get(CaseDeleteAction.class).setEnabled(
false);
 
 1555             hostPath = Paths.get(caseDirectory);
 
 1557         if (!hostPath.toFile().exists()) {
 
 1558             hostPath.toFile().mkdirs();
 
 1560         return hostPath.toString();
 
 1567         return Paths.get(System.getProperty(
"java.io.tmpdir"), 
APP_NAME, 
getName());
 
 1579         Path basePath = null;
 
 1584                 basePath = (StringUtils.isBlank(customDirectory))
 
 1586                         : Paths.get(customDirectory, APP_NAME, 
getName());
 
 1604                 : Paths.get(TEMP_FOLDER);
 
 1606         File caseTempDir = basePath
 
 1607                 .resolve(caseRelPath)
 
 1611         if (!caseTempDir.exists()) {
 
 1612             caseTempDir.mkdirs();
 
 1615         return caseTempDir.getAbsolutePath();
 
 1688             return path.subpath(path.getNameCount() - 2, path.getNameCount()).toString();
 
 1690             return path.subpath(path.getNameCount() - 1, path.getNameCount()).toString();
 
 1704         return caseDb.getRootObjects();
 
 1713         Set<TimeZone> timezones = 
new HashSet<>();
 
 1714         String query = 
"SELECT time_zone FROM data_source_info";
 
 1715         try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
 
 1716             ResultSet timeZoneSet = dbQuery.getResultSet();
 
 1717             while (timeZoneSet.next()) {
 
 1718                 String timeZone = timeZoneSet.getString(
"time_zone");
 
 1719                 if (timeZone != null && !timeZone.isEmpty()) {
 
 1720                     timezones.add(TimeZone.getTimeZone(timeZone));
 
 1723         } 
catch (TskCoreException | SQLException ex) {
 
 1724             logger.log(Level.SEVERE, 
"Error getting data source time zones", ex); 
 
 1768         hasDataSource = 
true;
 
 1876             logger.log(Level.WARNING, 
"Unable to send notifcation regarding comment change due to no current case being open", ex);
 
 1926     public void addReport(String localPath, String srcModuleName, String reportName) 
throws TskCoreException {
 
 1927         addReport(localPath, srcModuleName, reportName, null);
 
 1944     public Report 
addReport(String localPath, String srcModuleName, String reportName, Content parent) 
throws TskCoreException {
 
 1945         String normalizedLocalPath;
 
 1947             if (localPath.toLowerCase().contains(
"http:")) {
 
 1948                 normalizedLocalPath = localPath;
 
 1950                 normalizedLocalPath = Paths.get(localPath).normalize().toString();
 
 1952         } 
catch (InvalidPathException ex) {
 
 1953             String errorMsg = 
"Invalid local path provided: " + localPath; 
 
 1954             throw new TskCoreException(errorMsg, ex);
 
 1958         Report report = this.caseDb.addReport(normalizedLocalPath, srcModuleName, reportName, parent);
 
 1972         return this.caseDb.getAllReports();
 
 1983     public void deleteReports(Collection<? extends Report> reports) 
throws TskCoreException {
 
 1984         for (Report report : reports) {
 
 1985             this.caseDb.deleteReport(report);
 
 1990         } 
catch (TskCoreException ex) {
 
 1991             logger.log(Level.SEVERE, 
"Unable to retrieve the hasData status from the db", ex);
 
 1994         for (Report report : reports) {
 
 2016         "Case.exceptionMessage.metadataUpdateError=Failed to update case metadata" 
 2018     void updateCaseDetails(CaseDetails caseDetails) 
throws CaseActionException {
 
 2021             metadata.setCaseDetails(caseDetails);
 
 2022         } 
catch (CaseMetadataException ex) {
 
 2023             throw new CaseActionException(Bundle.Case_exceptionMessage_metadataUpdateError(), ex);
 
 2027                 CaseNodeData nodeData = CaseNodeData.readCaseNodeData(metadata.
getCaseDirectory());
 
 2029                 CaseNodeData.writeCaseNodeData(nodeData);
 
 2030             } 
catch (CaseNodeDataException | InterruptedException ex) {
 
 2031                 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotUpdateCaseNodeData(ex.getLocalizedMessage()), ex);
 
 2034         if (!oldCaseDetails.getCaseNumber().equals(caseDetails.
getCaseNumber())) {
 
 2035             eventPublisher.
publish(
new AutopsyEvent(Events.NUMBER.toString(), oldCaseDetails.getCaseNumber(), caseDetails.
getCaseNumber()));
 
 2037         if (!oldCaseDetails.getExaminerName().equals(caseDetails.
getExaminerName())) {
 
 2038             eventPublisher.
publish(
new AutopsyEvent(Events.NUMBER.toString(), oldCaseDetails.getExaminerName(), caseDetails.
getExaminerName()));
 
 2041             eventPublisher.
publish(
new AutopsyEvent(Events.NAME.toString(), oldCaseDetails.getCaseDisplayName(), caseDetails.
getCaseDisplayName()));
 
 2043         eventPublisher.
publish(
new AutopsyEvent(Events.CASE_DETAILS.toString(), oldCaseDetails, caseDetails));
 
 2044         if (RuntimeProperties.runningWithGUI()) {
 
 2045             SwingUtilities.invokeLater(() -> {
 
 2049                 } 
catch (Exception ex) {
 
 2050                     logger.log(Level.SEVERE, 
"Error updating case name in UI", ex); 
 
 2078         metadata = caseMetaData;
 
 2112         "Case.progressIndicatorCancelButton.label=Cancel",
 
 2113         "Case.progressMessage.preparing=Preparing...",
 
 2114         "Case.progressMessage.cancelling=Cancelling...",
 
 2115         "Case.exceptionMessage.cancelled=Cancelled.",
 
 2116         "# {0} - exception message", 
"Case.exceptionMessage.execExceptionWrapperMessage={0}" 
 2126             if (allowCancellation) {
 
 2130                         progressIndicatorTitle,
 
 2131                         new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
 
 2132                         Bundle.Case_progressIndicatorCancelButton_label(),
 
 2133                         cancelButtonListener);
 
 2137                         progressIndicatorTitle);
 
 2142         progressIndicator.
start(Bundle.Case_progressMessage_preparing());
 
 2151         caseActionExecutor = Executors.newSingleThreadExecutor(threadFactory);
 
 2152         Future<Void> future = caseActionExecutor.submit(() -> {
 
 2154                 caseAction.
execute(progressIndicator, additionalParams);
 
 2158                     if (null == resourcesLock) {
 
 2159                         throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock());
 
 2161                     caseAction.
execute(progressIndicator, additionalParams);
 
 2162                 } 
catch (CaseActionException ex) {
 
 2169         if (null != cancelButtonListener) {
 
 2178         } 
catch (InterruptedException discarded) {
 
 2182             if (null != cancelButtonListener) {
 
 2185                 future.cancel(
true);
 
 2188         } 
catch (CancellationException discarded) {
 
 2194         } 
catch (ExecutionException ex) {
 
 2199             throw new CaseActionException(Bundle.Case_exceptionMessage_execExceptionWrapperMessage(ex.getCause().getLocalizedMessage()), ex);
 
 2201             progressIndicator.
finish();
 
 2221         assert (additionalParams == null);
 
 2242         } 
catch (CaseActionException ex) {
 
 2251             } 
catch (InterruptedException discarded) {
 
 2253             close(progressIndicator);
 
 2273         assert (additionalParams == null);
 
 2293         } 
catch (CaseActionException ex) {
 
 2302             } 
catch (InterruptedException discarded) {
 
 2304             close(progressIndicator);
 
 2319         "# {0} - case", 
"Case.openFileSystems.retrievingImages=Retrieving images for case: {0}...",
 
 2320         "# {0} - image", 
"Case.openFileSystems.openingImage=Opening all filesystems for image: {0}..." 
 2323         if (backgroundOpenFileSystemsFuture != null && !backgroundOpenFileSystemsFuture.isDone()) {
 
 2324             backgroundOpenFileSystemsFuture.cancel(
true);
 
 2353             caseName = (this.tskCase != null) ? this.tskCase.getDatabaseName() : 
"";
 
 2364             if (Thread.interrupted()) {
 
 2365                 throw new InterruptedException();
 
 2375             progressIndicator.
progress(Bundle.Case_openFileSystems_retrievingImages(caseName));
 
 2377                 return this.tskCase.getImages();
 
 2378             } 
catch (TskCoreException ex) {
 
 2381                         String.format(
"Could not obtain images while opening case: %s.", caseName),
 
 2397         private void openFileSystems(List<Image> images) 
throws TskCoreException, InterruptedException {
 
 2398             byte[] tempBuff = 
new byte[512];
 
 2400             for (Image image : images) {
 
 2401                 String imageStr = image.getName();
 
 2403                 progressIndicator.
progress(Bundle.Case_openFileSystems_openingImage(imageStr));
 
 2405                 Collection<FileSystem> fileSystems = this.tskCase.getImageFileSystems(image);
 
 2407                 for (FileSystem fileSystem : fileSystems) {
 
 2408                     fileSystem.read(tempBuff, 0, 512);
 
 2420                 if (images == null) {
 
 2428                             String.format(
"Skipping background load of file systems due to large number of images in case (%d)", images.size()));
 
 2434             } 
catch (InterruptedException ex) {
 
 2437                         String.format(
"Background operation opening all file systems in %s has been cancelled.", caseName));
 
 2438             } 
catch (Exception ex) {
 
 2440                 logger.log(Level.WARNING, 
"Error while opening file systems in background", ex);
 
 2461         "Case.progressMessage.deletingDataSource=Removing the data source from the case...",
 
 2462         "Case.exceptionMessage.dataSourceNotFound=The data source was not found.",
 
 2463         "Case.exceptionMessage.errorDeletingDataSourceFromCaseDb=An error occurred while removing the data source from the case database.",
 
 2464         "Case.exceptionMessage.errorDeletingDataSourceFromTextIndex=An error occurred while removing the data source from the text index.",})
 
 2465     Void deleteDataSource(ProgressIndicator progressIndicator, Object additionalParams) 
throws CaseActionException {
 
 2466         assert (additionalParams instanceof Long);
 
 2467         open(progressIndicator, null);
 
 2469             progressIndicator.progress(Bundle.Case_progressMessage_deletingDataSource());
 
 2470             Long dataSourceObjectID = (Long) additionalParams;
 
 2472                 DataSource dataSource = this.caseDb.getDataSource(dataSourceObjectID);
 
 2473                 if (dataSource == null) {
 
 2474                     throw new CaseActionException(Bundle.Case_exceptionMessage_dataSourceNotFound());
 
 2476                 SleuthkitCaseAdminUtil.deleteDataSource(this.caseDb, dataSourceObjectID);
 
 2477             } 
catch (TskDataException | TskCoreException ex) {
 
 2478                 throw new CaseActionException(Bundle.Case_exceptionMessage_errorDeletingDataSourceFromCaseDb(), ex);
 
 2482             } 
catch (KeywordSearchServiceException ex) {
 
 2483                 throw new CaseActionException(Bundle.Case_exceptionMessage_errorDeletingDataSourceFromTextIndex(), ex);
 
 2485             eventPublisher.
publish(
new DataSourceDeletedEvent(dataSourceObjectID));
 
 2488             close(progressIndicator);
 
 2503     public SleuthkitCase 
createPortableCase(String caseName, File portableCaseFolder) 
throws TskCoreException {
 
 2505         if (portableCaseFolder.exists()) {
 
 2506             throw new TskCoreException(
"Portable case folder " + portableCaseFolder.toString() + 
" already exists");
 
 2508         if (!portableCaseFolder.mkdirs()) {
 
 2509             throw new TskCoreException(
"Error creating portable case folder " + portableCaseFolder.toString());
 
 2517             portableCaseMetadata.setCaseDatabaseName(SINGLE_USER_CASE_DB_NAME);
 
 2519             throw new TskCoreException(
"Error creating case metadata", ex);
 
 2523         SleuthkitCase portableSleuthkitCase;
 
 2525         portableSleuthkitCase = SleuthkitCase.newCase(dbFilePath);
 
 2527         return portableSleuthkitCase;
 
 2540         if (Thread.currentThread().isInterrupted()) {
 
 2541             throw new CaseActionCancelledException(Bundle.Case_exceptionMessage_cancelled());
 
 2556         "Case.progressMessage.creatingCaseDirectory=Creating case directory..." 
 2563         progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDirectory());
 
 2565             progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDirectory());
 
 2577         "Case.progressMessage.switchingLogDirectory=Switching log directory..." 
 2580         progressIndicator.
progress(Bundle.Case_progressMessage_switchingLogDirectory());
 
 2596         "Case.progressMessage.savingCaseMetadata=Saving case metadata to file...",
 
 2597         "# {0} - exception message", 
"Case.exceptionMessage.couldNotSaveCaseMetadata=Failed to save case metadata:\n{0}." 
 2600         progressIndicator.
progress(Bundle.Case_progressMessage_savingCaseMetadata());
 
 2602             this.metadata.writeToFile();
 
 2604             throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotSaveCaseMetadata(ex.getLocalizedMessage()), ex);
 
 2620         "Case.progressMessage.creatingCaseNodeData=Creating coordination service node data...",
 
 2621         "# {0} - exception message", 
"Case.exceptionMessage.couldNotCreateCaseNodeData=Failed to create coordination service node data:\n{0}." 
 2625             progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseNodeData());
 
 2629                 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateCaseNodeData(ex.getLocalizedMessage()), ex);
 
 2646         "Case.progressMessage.updatingCaseNodeData=Updating coordination service node data...",
 
 2647         "# {0} - exception message", 
"Case.exceptionMessage.couldNotUpdateCaseNodeData=Failed to update coordination service node data:\n{0}." 
 2651             progressIndicator.
progress(Bundle.Case_progressMessage_updatingCaseNodeData());
 
 2657                 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotUpdateCaseNodeData(ex.getLocalizedMessage()), ex);
 
 2668         "Case.progressMessage.clearingTempDirectory=Clearing case temp directory..." 
 2674         progressIndicator.
progress(Bundle.Case_progressMessage_clearingTempDirectory());
 
 2690         "Case.progressMessage.creatingCaseDatabase=Creating case database...",
 
 2691         "# {0} - exception message", 
"Case.exceptionMessage.couldNotGetDbServerConnectionInfo=Failed to get case database server conneciton info:\n{0}.",
 
 2692         "# {0} - exception message", 
"Case.exceptionMessage.couldNotCreateCaseDatabase=Failed to create case database:\n{0}.",
 
 2693         "# {0} - exception message", 
"Case.exceptionMessage.couldNotSaveDbNameToMetadataFile=Failed to save case database name to case metadata file:\n{0}." 
 2696         progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDatabase());
 
 2705                 metadata.setCaseDatabaseName(SINGLE_USER_CASE_DB_NAME);
 
 2713                 metadata.setCaseDatabaseName(caseDb.getDatabaseName());
 
 2715         } 
catch (TskCoreException ex) {
 
 2716             throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateCaseDatabase(ex.getLocalizedMessage()), ex);
 
 2718             throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotGetDbServerConnectionInfo(ex.getLocalizedMessage()), ex);
 
 2720             throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotSaveDbNameToMetadataFile(ex.getLocalizedMessage()), ex);
 
 2736         "Case.progressMessage.openingCaseDatabase=Opening case database...",
 
 2737         "# {0} - exception message", 
"Case.exceptionMessage.couldNotOpenCaseDatabase=Failed to open case database:\n{0}.",
 
 2738         "# {0} - exception message", 
"Case.exceptionMessage.unsupportedSchemaVersionMessage=Unsupported case database schema version:\n{0}.",
 
 2739         "Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-User." 
 2742         progressIndicator.
progress(Bundle.Case_progressMessage_openingCaseDatabase());
 
 2746                 caseDb = SleuthkitCase.openCase(Paths.get(metadata.
getCaseDirectory(), databaseName).toString());
 
 2750                 throw new CaseActionException(Bundle.Case_open_exception_multiUserCaseNotEnabled());
 
 2753         } 
catch (TskUnsupportedSchemaVersionException ex) {
 
 2754             throw new CaseActionException(Bundle.Case_exceptionMessage_unsupportedSchemaVersionMessage(ex.getLocalizedMessage()), ex);
 
 2756             throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotGetDbServerConnectionInfo(ex.getLocalizedMessage()), ex);
 
 2757         } 
catch (TskCoreException ex) {
 
 2758             throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotOpenCaseDatabase(ex.getLocalizedMessage()), ex);
 
 2769         "Case.progressMessage.openingCaseLevelServices=Opening case-level services...",})
 
 2771         progressIndicator.
progress(Bundle.Case_progressMessage_openingCaseLevelServices());
 
 2772         this.caseServices = 
new Services(caseDb);
 
 2778         caseDb.registerForEvents(sleuthkitEventListener);
 
 2793     @NbBundle.Messages({
 
 2794         "Case.progressMessage.openingApplicationServiceResources=Opening application service case resources...",
 
 2795         "# {0} - service name", 
"Case.serviceOpenCaseResourcesProgressIndicator.title={0} Opening Case Resources",
 
 2796         "# {0} - service name", 
"Case.serviceOpenCaseResourcesProgressIndicator.cancellingMessage=Cancelling opening case resources by {0}...",
 
 2797         "# {0} - service name", 
"Case.servicesException.notificationTitle={0} Error" 
 2808         progressIndicator.
progress(Bundle.Case_progressMessage_openingApplicationServiceResources());
 
 2820                 cancelButtonListener = 
new CancelButtonListener(Bundle.Case_serviceOpenCaseResourcesProgressIndicator_cancellingMessage(service.getServiceName()));
 
 2823                         Bundle.Case_serviceOpenCaseResourcesProgressIndicator_title(service.getServiceName()),
 
 2824                         new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
 
 2825                         Bundle.Case_progressIndicatorCancelButton_label(),
 
 2826                         cancelButtonListener);
 
 2830             appServiceProgressIndicator.
start(Bundle.Case_progressMessage_preparing());
 
 2832             String threadNameSuffix = service.getServiceName().replaceAll(
"[ ]", 
"-"); 
 
 2833             threadNameSuffix = threadNameSuffix.toLowerCase();
 
 2835             ExecutorService executor = Executors.newSingleThreadExecutor(threadFactory);
 
 2836             Future<Void> future = executor.submit(() -> {
 
 2837                 service.openCaseResources(context);
 
 2840             if (null != cancelButtonListener) {
 
 2852             } 
catch (InterruptedException discarded) {
 
 2857                 future.cancel(
true);
 
 2858             } 
catch (CancellationException discarded) {
 
 2866             } 
catch (ExecutionException ex) {
 
 2873                 Case.
logger.log(Level.SEVERE, String.format(
"%s failed to open case resources for %s", service.getServiceName(), this.
getDisplayName()), ex);
 
 2875                     SwingUtilities.invokeLater(() -> {
 
 2887                 appServiceProgressIndicator.
finish();
 
 2905         "Case.progressMessage.settingUpNetworkCommunications=Setting up network communications...",
 
 2906         "# {0} - exception message", 
"Case.exceptionMessage.couldNotOpenRemoteEventChannel=Failed to open remote events channel:\n{0}.",
 
 2907         "# {0} - exception message", 
"Case.exceptionMessage.couldNotCreatCollaborationMonitor=Failed to create collaboration monitor:\n{0}." 
 2911             progressIndicator.
progress(Bundle.Case_progressMessage_settingUpNetworkCommunications());
 
 2915                 collaborationMonitor = 
new CollaborationMonitor(metadata.
getCaseName());
 
 2917                 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotOpenRemoteEventChannel(ex.getLocalizedMessage()), ex);
 
 2918             } 
catch (CollaborationMonitor.CollaborationMonitorException ex) {
 
 2919                 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreatCollaborationMonitor(ex.getLocalizedMessage()), ex);
 
 2947                     Bundle.Case_progressIndicatorTitle_closingCase());
 
 2951         progressIndicator.
start(Bundle.Case_progressMessage_preparing());
 
 2960         Future<Void> future = caseActionExecutor.submit(() -> {
 
 2962                 close(progressIndicator);
 
 2969                 progressIndicator.
progress(Bundle.Case_progressMessage_preparing());
 
 2971                     if (null == resourcesLock) {
 
 2972                         throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock());
 
 2974                     close(progressIndicator);
 
 2988         } 
catch (InterruptedException | CancellationException unused) {
 
 2995         } 
catch (ExecutionException ex) {
 
 2996             throw new CaseActionException(Bundle.Case_exceptionMessage_execExceptionWrapperMessage(ex.getCause().getMessage()), ex);
 
 2999             progressIndicator.
finish();
 
 3009         "Case.progressMessage.shuttingDownNetworkCommunications=Shutting down network communications...",
 
 3010         "Case.progressMessage.closingApplicationServiceResources=Closing case-specific application service resources...",
 
 3011         "Case.progressMessage.closingCaseDatabase=Closing case database..." 
 3021             progressIndicator.
progress(Bundle.Case_progressMessage_shuttingDownNetworkCommunications());
 
 3022             if (null != collaborationMonitor) {
 
 3023                 collaborationMonitor.shutdown();
 
 3032         progressIndicator.
progress(Bundle.Case_progressMessage_closingApplicationServiceResources());
 
 3038         if (null != caseDb) {
 
 3039             progressIndicator.
progress(Bundle.Case_progressMessage_closingCaseDatabase());
 
 3040             caseDb.unregisterForEvents(sleuthkitEventListener);
 
 3052         progressIndicator.
progress(Bundle.Case_progressMessage_switchingLogDirectory());
 
 3061         "# {0} - serviceName", 
"Case.serviceCloseResourcesProgressIndicator.title={0} Closing Case Resources",
 
 3062         "# {0} - service name", 
"# {1} - exception message", 
"Case.servicesException.serviceResourcesCloseError=Could not close case resources for {0} service: {1}" 
 3075                         Bundle.Case_serviceCloseResourcesProgressIndicator_title(service.getServiceName()));
 
 3079             progressIndicator.
start(Bundle.Case_progressMessage_preparing());
 
 3081             String threadNameSuffix = service.getServiceName().replaceAll(
"[ ]", 
"-"); 
 
 3082             threadNameSuffix = threadNameSuffix.toLowerCase();
 
 3084             ExecutorService executor = Executors.newSingleThreadExecutor(threadFactory);
 
 3085             Future<Void> future = executor.submit(() -> {
 
 3086                 service.closeCaseResources(context);
 
 3091             } 
catch (InterruptedException ex) {
 
 3092                 Case.
logger.log(Level.SEVERE, String.format(
"Unexpected interrupt while waiting on %s service to close case resources", service.getServiceName()), ex);
 
 3093             } 
catch (CancellationException ex) {
 
 3094                 Case.
logger.log(Level.SEVERE, String.format(
"Unexpected cancellation while waiting on %s service to close case resources", service.getServiceName()), ex);
 
 3095             } 
catch (ExecutionException ex) {
 
 3096                 Case.
logger.log(Level.SEVERE, String.format(
"%s service failed to open case resources", service.getServiceName()), ex);
 
 3099                             Bundle.Case_servicesException_notificationTitle(service.getServiceName()),
 
 3100                             Bundle.Case_servicesException_serviceResourcesCloseError(service.getServiceName(), ex.getLocalizedMessage())));
 
 3104                 progressIndicator.
finish();
 
 3115         "Case.lockingException.couldNotAcquireSharedLock=Failed to get a shared lock on the case.",
 
 3116         "Case.lockingException.couldNotAcquireExclusiveLock=Failed to get an exclusive lock on the case." 
 3127                     throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireSharedLock());
 
 3129                     throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireExclusiveLock());
 
 3134                 throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireSharedLock(), ex);
 
 3136                 throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireExclusiveLock(), ex);
 
 3150                 logger.log(Level.SEVERE, String.format(
"Failed to release shared case directory lock for %s", 
getMetadata().
getCaseDirectory()), ex);
 
 3163         if (!subDirectory.exists()) {
 
 3164             subDirectory.mkdirs();
 
 3166         return subDirectory.toString();
 
 3182         "Case.exceptionMessage.errorsDeletingCase=Errors occured while deleting the case. See the application log for details." 
 3185         boolean errorsOccurred = 
false;
 
 3189             errorsOccurred = 
true;
 
 3195         } 
catch (CaseActionException ex) {
 
 3196             errorsOccurred = 
true;
 
 3202         if (errorsOccurred) {
 
 3203             throw new CaseActionException(Bundle.Case_exceptionMessage_errorsDeletingCase());
 
 3227         "Case.progressMessage.connectingToCoordSvc=Connecting to coordination service...",
 
 3228         "# {0} - exception message", 
"Case.exceptionMessage.failedToConnectToCoordSvc=Failed to connect to coordination service:\n{0}.",
 
 3229         "Case.exceptionMessage.cannotGetLockToDeleteCase=Cannot delete case because it is open for another user or host.",
 
 3230         "# {0} - exception message", 
"Case.exceptionMessage.failedToLockCaseForDeletion=Failed to exclusively lock case for deletion:\n{0}.",
 
 3231         "Case.progressMessage.fetchingCoordSvcNodeData=Fetching coordination service node data for the case...",
 
 3232         "# {0} - exception message", 
"Case.exceptionMessage.failedToFetchCoordSvcNodeData=Failed to fetch coordination service node data:\n{0}.",
 
 3233         "Case.progressMessage.deletingResourcesCoordSvcNode=Deleting case resources coordination service node...",
 
 3234         "Case.progressMessage.deletingCaseDirCoordSvcNode=Deleting case directory coordination service node..." 
 3237         progressIndicator.
progress(Bundle.Case_progressMessage_connectingToCoordSvc());
 
 3243             throw new CaseActionException(Bundle.Case_exceptionMessage_failedToConnectToCoordSvc(ex.getLocalizedMessage()));
 
 3247         boolean errorsOccurred = 
false;
 
 3249             if (dirLock == null) {
 
 3251                 throw new CaseActionException(Bundle.Case_exceptionMessage_cannotGetLockToDeleteCase());
 
 3254             progressIndicator.
progress(Bundle.Case_progressMessage_fetchingCoordSvcNodeData());
 
 3259                 throw new CaseActionException(Bundle.Case_exceptionMessage_failedToFetchCoordSvcNodeData(ex.getLocalizedMessage()));
 
 3264             progressIndicator.
progress(Bundle.Case_progressMessage_deletingResourcesCoordSvcNode());
 
 3270                     errorsOccurred = 
true;
 
 3271                     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); 
 
 3273             } 
catch (InterruptedException ex) {
 
 3274                 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); 
 
 3279             throw new CaseActionException(Bundle.Case_exceptionMessage_failedToLockCaseForDeletion(ex.getLocalizedMessage()));
 
 3282         if (!errorsOccurred) {
 
 3283             progressIndicator.
progress(Bundle.Case_progressMessage_deletingCaseDirCoordSvcNode());
 
 3289                 errorsOccurred = 
true;
 
 3293         if (errorsOccurred) {
 
 3294             throw new CaseActionException(Bundle.Case_exceptionMessage_errorsDeletingCase());
 
 3324         boolean errorsOccurred = 
false;
 
 3331             errorsOccurred = 
true;
 
 3334             errorsOccurred = 
true;
 
 3336         } 
catch (CaseActionException ex) {
 
 3337             errorsOccurred = 
true;
 
 3340         return errorsOccurred;
 
 3364         "Case.progressMessage.deletingCaseDatabase=Deleting case database..." 
 3368             progressIndicator.
progress(Bundle.Case_progressMessage_deletingCaseDatabase());
 
 3369             logger.log(Level.INFO, String.format(
"Deleting case database for %s (%s) in %s", caseNodeData.
getDisplayName(), caseNodeData.
getName(), caseNodeData.
getDirectory())); 
 
 3371             String url = 
"jdbc:postgresql://" + info.getHost() + 
":" + info.getPort() + 
"/postgres"; 
 
 3372             Class.forName(
"org.postgresql.Driver"); 
 
 3373             try (Connection connection = DriverManager.getConnection(url, info.getUserName(), info.getPassword()); Statement statement = connection.createStatement()) {
 
 3374                 String dbExistsQuery = 
"SELECT 1 from pg_database WHERE datname = '" + metadata.
getCaseDatabaseName() + 
"'"; 
 
 3375                 try (ResultSet queryResult = statement.executeQuery(dbExistsQuery)) {
 
 3376                     if (queryResult.next()) {
 
 3378                         statement.execute(deleteCommand);
 
 3419         "Case.progressMessage.deletingTextIndex=Deleting text index..." 
 3422         progressIndicator.
progress(Bundle.Case_progressMessage_deletingTextIndex());
 
 3426             searchService.deleteTextIndex(metadata);
 
 3462         "Case.progressMessage.deletingCaseDirectory=Deleting case directory..." 
 3465         progressIndicator.
progress(Bundle.Case_progressMessage_deletingCaseDirectory());
 
 3467             throw new CaseActionException(String.format(
"Failed to delete %s", metadata.
getCaseDirectory())); 
 
 3479         "Case.progressMessage.removingCaseFromRecentCases=Removing case from Recent Cases menu..." 
 3483             progressIndicator.
progress(Bundle.Case_progressMessage_removingCaseFromRecentCases());
 
 3484             SwingUtilities.invokeLater(() -> {
 
 3500         boolean isNodeNodeEx = 
false;
 
 3501         Throwable cause = ex.getCause();
 
 3502         if (cause != null) {
 
 3503             String causeMessage = cause.getMessage();
 
 3504             isNodeNodeEx = causeMessage.contains(NO_NODE_ERROR_MSG_FRAGMENT);
 
 3506         return isNodeNodeEx;
 
 3525             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);
 
 3544         if (!hasDataSource) {
 
 3559         String query = 
"SELECT count(*) AS count FROM (SELECT * FROM data_source_info LIMIT 1)t";
 
 3560         try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
 
 3561             ResultSet resultSet = dbQuery.getResultSet();
 
 3562             if (resultSet.next()) {
 
 3563                 return resultSet.getLong(
"count") > 0;
 
 3566         } 
catch (SQLException ex) {
 
 3567             logger.log(Level.SEVERE, 
"Error accessing case database", ex); 
 
 3568             throw new TskCoreException(
"Error accessing case databse", ex);
 
 3583         String query = 
"SELECT SUM(cnt) total FROM " 
 3584                 + 
"(SELECT COUNT(*) AS cnt FROM " 
 3585                 + 
"(SELECT * FROM tsk_objects LIMIT 1)t " 
 3587                 + 
"SELECT COUNT(*) AS cnt FROM " 
 3588                 + 
"(SELECT * FROM tsk_hosts LIMIT 1)r) s";
 
 3589         try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
 
 3590             ResultSet resultSet = dbQuery.getResultSet();
 
 3591             if (resultSet.next()) {
 
 3592                 return resultSet.getLong(
"total") > 0;
 
 3596         } 
catch (SQLException ex) {
 
 3597             logger.log(Level.SEVERE, 
"Error accessing case database", ex); 
 
 3598             throw new TskCoreException(
"Error accessing case databse", ex);
 
 3622         R 
execute(T progressIndicator, V additionalParams) 
throws CaseActionException;
 
 3720                         ((ModalDialogProgressIndicator) progressIndicator).
setCancelling(cancellationMessage);
 
 3749             return new Thread(task, threadName);
 
 3786     public static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner) 
throws CaseActionException {
 
 3811     public static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner, 
CaseType caseType) 
throws CaseActionException {
 
 3827     public static void open(String caseMetadataFilePath) 
throws CaseActionException {
 
 3884         return new File(filePath).isFile();
 
 3923         return "ModuleOutput"; 
 
 3936     public static PropertyChangeSupport
 
 3938         return new PropertyChangeSupport(
Case.class
 
 3970     public Image 
addImage(String imgPath, 
long imgId, String timeZone) 
throws CaseActionException {
 
 3972             Image newDataSource = caseDb.getImageById(imgId);
 
 3974             return newDataSource;
 
 3975         } 
catch (TskCoreException ex) {
 
 3976             throw new CaseActionException(NbBundle.getMessage(
this.getClass(), 
"Case.addImg.exception.msg"), ex);
 
 4003     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)
void publicTagNamesAdded(TskEvent.TagNamesAddedTskEvent event)
static void invokeStartupDialog()
void updateDataParameters()
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)
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)
void publicTagSetsDeleted(TskEvent.TagSetsDeletedTskEvent event)
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)
void publicTagNamesUpdated(TskEvent.TagNamesUpdatedTskEvent event)
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)
void publicTagNamesDeleted(TskEvent.TagNamesDeletedTskEvent event)
static boolean isCaseOpen()
String getTextIndexName()
static final String REPORTS_FOLDER
void progress(String message)
HOSTS_REMOVED_FROM_PERSON
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)
void publicTagSetsAdded(TskEvent.TagSetsAddedTskEvent event)
final SleuthkitCase tskCase
String getExaminerEmail()