From ec68fa3b288033c814a61b0fbb745669b17a7305 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Wed, 18 May 2016 12:51:31 -0400 Subject: [PATCH 1/3] Partial cleanup of FileManager --- .../casemodule/services/Bundle.properties | 13 - .../casemodule/services/Bundle_ja.properties | 13 - .../casemodule/services/FileManager.java | 653 ++++++++---------- .../autopsy/casemodule/services/Services.java | 17 +- 4 files changed, 322 insertions(+), 374 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties index 9353ca914b..1a3be9454f 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties @@ -1,16 +1,3 @@ -FileManager.findFiles.exception.msg=Attempted to use FileManager after it was closed. -FileManager.findFiles2.exception.msg=Attempted to use FileManager after it was closed. -FileManager.findFiles3.exception.msg=Attempted to use FileManager after it was closed. -FileManager.openFiles.exception.msg=Attempted to use FileManager after it was closed. -FileManager.addDerivedFile.exception.msg=Attempted to use FileManager after it was closed. -FileManager.addCarvedFile.exception.msg=Attempted to use FileManager after it was closed. -FileManager.addLocalFilesDirs.exception.notReadable.msg=One of the local files/dirs to add is not readable\: {0}, aborting the process before any files added -FileManager.addLocalFilesDirs.exception.cantAdd.msg=One of the local files/dirs could not be added\: {0} -FileManager.addLocalFileSetRootDir.exception.errCreateDir.msg=Error creating local file set dir\: {0} -FileManager.addLocalDirInt.exception.closed.msg=Attempted to use FileManager after it was closed. -FileManager.addLocalDirInt.exception.doesntExist.msg=Attempted to add a local dir that does not exist\: {0} -FileManager.addLocalDirInt.exception.notReadable.msg=Attempted to add a local dir that is not readable\: {0} -FileManager.addLocalDirInt2.exception.closed.msg=Attempted to use FileManager after it was closed. TagsManager.addContentTag.exception.beginByteOffsetOOR.msg=beginByteOffset \= {0} out of content size range (0 - {1}) TagsManager.addContentTag.exception.endByteOffsetOOR.msg=endByteOffset \= {0} out of content size range (0 - {1}) TagsManager.addContentTag.exception.endLTbegin.msg=endByteOffset < beginByteOffset diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties index 956a5e6169..ca8ed3431a 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties @@ -1,16 +1,3 @@ -FileManager.findFiles.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002 -FileManager.findFiles2.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002 -FileManager.findFiles3.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002 -FileManager.openFiles.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002 -FileManager.addDerivedFile.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002 -FileManager.addCarvedFile.exception.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002 -FileManager.addLocalFilesDirs.exception.notReadable.msg=\u8ffd\u52a0\u3059\u308b\u30ed\u30fc\u30ab\u30eb\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u4e2d\u306b\u8aad\u307f\u53d6\u308c\u306a\u3044\u3082\u306e\u304c\uff11\u500b\u3042\u308a\u307e\u3059\uff1a{0}\u3001\u30d5\u30a1\u30a4\u30eb\u304c\u8ffd\u52a0\u3055\u308c\u308b\u524d\u306b\u51e6\u7406\u3092\u4e2d\u6b62\u3057\u307e\u3059 -FileManager.addLocalFilesDirs.exception.cantAdd.msg=\u30ed\u30fc\u30ab\u30eb\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\uff11\u500b\u306f\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\uff1a{0} -FileManager.addLocalFileSetRootDir.exception.errCreateDir.msg=\u30ed\u30fc\u30ab\u30eb\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u8d77\u3053\u308a\u307e\u3057\u305f\uff1a {0} -FileManager.addLocalDirInt.exception.closed.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002 -FileManager.addLocalDirInt.exception.doesntExist.msg=\u5b58\u5728\u3057\u306a\u3044\u30ed\u30fc\u30ab\u30eb\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u8ffd\u52a0\u3092\u8a66\u307f\u307e\u3057\u305f\: {0} -FileManager.addLocalDirInt.exception.notReadable.msg=\u8aad\u307f\u53d6\u308a\u3067\u304d\u306a\u3044\u30ed\u30fc\u30ab\u30eb\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u8ffd\u52a0\u3092\u8a66\u307f\u307e\u3057\u305f\: {0} -FileManager.addLocalDirInt2.exception.closed.msg=FileManager\u3092\u9589\u3058\u305f\u5f8c\u306b\u4f7f\u7528\u3092\u8a66\u307f\u307e\u3057\u305f\u3002 TagsManager.addContentTag.exception.beginByteOffsetOOR.msg=beginByteOffset \= {0} \u30b3\u30f3\u30c6\u30f3\u30c4\u30b5\u30a4\u30ba\u7bc4\u56f2(0 - {1})\u306e\u5916\u3067\u3059 TagsManager.addContentTag.exception.endByteOffsetOOR.msg=endByteOffset \= {0} \u30b3\u30f3\u30c6\u30f3\u30c4\u30b5\u30a4\u30ba\u7bc4\u56f2(0 - {1})\u306e\u5916\u3067\u3059 TagsManager.addContentTag.exception.endLTbegin.msg=endByteOffset < beginByteOffset diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java index 5b958cd5a7..336e97742b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java @@ -1,19 +1,19 @@ /* * * Autopsy Forensic Browser - * + * * Copyright 2011-2016 Basis Technology Corp. - * + * * Copyright 2012 42six Solutions. * Contact: aebadirad 42six com * Project Contact/Architect: carrier sleuthkit org - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; import org.sleuthkit.autopsy.ingest.IngestServices; @@ -47,56 +48,75 @@ import org.sleuthkit.datamodel.LocalFilesDataSource; import org.sleuthkit.datamodel.TskDataException; /** - * Abstraction to facilitate access to localFiles and directories. + * A case-level service that provides methods for retrieving files associated + * with the case and for adding local files, carved files, and derived files to + * the case. */ public class FileManager implements Closeable { - private SleuthkitCase tskCase; private static final Logger logger = Logger.getLogger(FileManager.class.getName()); - private volatile int curNumFileSets; //current number of filesets (root virt dir objects) + private SleuthkitCase caseDb; - public FileManager(SleuthkitCase tskCase) { - this.tskCase = tskCase; - init(); + /* + * TODO (AUT-1905): Although this counter is guarded by the monitor of the + * FileManager, this does not guarantee unique default file set names for + * multi-user cases where multiple nodes can be running FileManagers for the + * same case. + */ + private int localFileDataSourcesCounter; + + /** + * Constructs a case-level service that provides methods for retrieving + * files associated with the case and for adding local files, carved files, + * and derived files to the case. + */ + FileManager(Case currentCase, SleuthkitCase caseDb) throws TskCoreException { + this.caseDb = caseDb; + initializeLocalFileDataSourcesCounter(); } /** - * initialize the file manager for the case + * Initialize the counter for the number of logical/local file sets that is + * used to generate the default logical/local file data source names. */ - private synchronized void init() { - //get the number of local file sets in db - List virtRoots; - curNumFileSets = 0; + private void initializeLocalFileDataSourcesCounter() { + /* + * TODO (AUT-1905): Although the counter is guarded by the monitor of + * the FileManager, this does not guarantee unique default file set + * names for multi-user cases where multiple nodes can be running + * FileManagers for the same case. + */ + localFileDataSourcesCounter = 0; try { - virtRoots = tskCase.getVirtualDirectoryRoots(); - for (VirtualDirectory vd : virtRoots) { + List localFileDataSources = caseDb.getVirtualDirectoryRoots(); + for (VirtualDirectory vd : localFileDataSources) { if (vd.getName().startsWith(VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX)) { - ++curNumFileSets; + ++localFileDataSourcesCounter; } } } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error initializing FileManager and getting number of local file sets"); //NON-NLS + logger.log(Level.SEVERE, "Error initializing logical files counter", ex); //NON-NLS } - } /** - * Finds a set of localFiles that meets the name criteria in all data - * sources in the current case. + * Finds all files and directories with a given file name. The name search + * is for full or partial matches and is case insensitive (a case + * insensitive SQL LIKE clause is used to query the case database). * - * @param fileName Pattern of the name of the file or directory to match - * (case insensitive, used in LIKE SQL statement). + * @param fileName The full or partial file name. * - * @return a list of AbstractFile for localFiles/directories whose name - * matches the given fileName + * @return The matching files and directories. + * + * @throws TskCoreException if there is a problem querying the case + * database. */ public synchronized List findFiles(String fileName) throws TskCoreException { - List result = new ArrayList<>(); - - if (tskCase == null) { - throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles.exception.msg")); + if (null == caseDb) { + throw new TskCoreException("FileManager closed"); } - List dataSources = tskCase.getRootObjects(); + List result = new ArrayList<>(); + List dataSources = caseDb.getRootObjects(); for (Content dataSource : dataSources) { result.addAll(findFiles(dataSource, fileName)); } @@ -104,113 +124,113 @@ public class FileManager implements Closeable { } /** - * Finds a set of localFiles that meets the name criteria in all data - * sources in the current case. + * Finds all files and directories with a given file name and parent file or + * directory name. The name searches are for full or partial matches and are + * case insensitive (a case insensitive SQL LIKE clause is used to query the + * case database). * - * @param fileName Pattern of the name of the file or directory to match - * (case insensitive, used in LIKE SQL statement). - * @param dirName Pattern of the name of the parent directory to use as the - * root of the search (case insensitive, used in LIKE SQL - * statement). + * @param fileName The full or partial file name. + * @param parentName The full or partial parent file or directory name. * - * @return a list of AbstractFile for localFiles/directories whose name - * matches fileName and whose parent directory contains dirName. + * @return The matching files and directories. + * + * @throws TskCoreException if there is a problem querying the case + * database. */ - public synchronized List findFiles(String fileName, String dirName) throws TskCoreException { - List result = new ArrayList<>(); - - if (tskCase == null) { - throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles2.exception.msg")); + public synchronized List findFiles(String fileName, String parentName) throws TskCoreException { + if (null == caseDb) { + throw new TskCoreException("FileManager closed"); } - List dataSources = tskCase.getRootObjects(); + List result = new ArrayList<>(); + List dataSources = caseDb.getRootObjects(); for (Content dataSource : dataSources) { - result.addAll(findFiles(dataSource, fileName, dirName)); + result.addAll(findFiles(dataSource, fileName, parentName)); } return result; } /** - * Finds a set of localFiles that meets the name criteria in all data - * sources in the current case. + * Finds all files and directories with a given file name and parent file or + * directory. The name search is for full or partial matches and is case + * insensitive (a case insensitive SQL LIKE clause is used to query the case + * database). * - * @param fileName Pattern of the name of the file or directory to match - * (case insensitive, used in LIKE SQL statement). - * @param parentFile Object of root/parent directory to restrict search to. + * @param fileName The full or partial file name. + * @param parent The parent file or directory. * - * @return a list of AbstractFile for localFiles/directories whose name - * matches fileName and that were inside a directory described by - * parentFsContent. + * @return The matching files and directories. + * + * @throws TskCoreException if there is a problem querying the case + * database. */ - public synchronized List findFiles(String fileName, AbstractFile parentFile) throws TskCoreException { - List result = new ArrayList<>(); - - if (tskCase == null) { - throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles3.exception.msg")); + public synchronized List findFiles(String fileName, AbstractFile parent) throws TskCoreException { + if (null == caseDb) { + throw new TskCoreException("FileManager closed"); } - List dataSources = tskCase.getRootObjects(); + List result = new ArrayList<>(); + List dataSources = caseDb.getRootObjects(); for (Content dataSource : dataSources) { - result.addAll(findFiles(dataSource, fileName, parentFile)); + result.addAll(findFiles(dataSource, fileName, parent)); } return result; } /** - * Finds a set of localFiles that meets the name criteria. + * Finds all files and directories with a given file name in a given data + * source (image, local/logical files set, etc.). The name search is for + * full or partial matches and is case insensitive (a case insensitive SQL + * LIKE clause is used to query the case database). * - * @param dataSource Root data source to limit search results to (Image, - * VirtualDirectory, etc.). - * @param fileName Pattern of the name of the file or directory to match - * (case insensitive, used in LIKE SQL statement). + * @param dataSource The data source. + * @param fileName The full or partial file name. * - * @return a list of AbstractFile for localFiles/directories whose name - * matches the given fileName + * @return The matching files and directories. + * + * @throws TskCoreException if there is a problem querying the case + * database. */ public synchronized List findFiles(Content dataSource, String fileName) throws TskCoreException { - if (tskCase == null) { - throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles.exception.msg")); - } - return tskCase.findFiles(dataSource, fileName); + return caseDb.findFiles(dataSource, fileName); } /** - * Finds a set of localFiles that meets the name criteria. + * Finds all files and directories with a given file name and parent file or + * directory name in a given data source (image, local/logical files set, + * etc.). The name searches are for full or partial matches and are case + * insensitive (a case insensitive SQL LIKE clause is used to query the case + * database). * - * @param dataSource Root data source to limit search results to (Image, - * VirtualDirectory, etc.). - * @param fileName Pattern of the name of the file or directory to match - * (case insensitive, used in LIKE SQL statement). - * @param dirName Pattern of the name of the parent directory to use as - * the root of the search (case insensitive, used in LIKE - * SQL statement). + * @param dataSource The data source. + * @param fileName The full or partial file name. + * @param parentName The full or partial parent file or directory name. * - * @return a list of AbstractFile for localFiles/directories whose name - * matches fileName and whose parent directory contains dirName. + * @return The matching files and directories. + * + * @throws TskCoreException if there is a problem querying the case + * database. */ - public synchronized List findFiles(Content dataSource, String fileName, String dirName) throws TskCoreException { - if (tskCase == null) { - throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles2.exception.msg")); - } - return tskCase.findFiles(dataSource, fileName, dirName); + public synchronized List findFiles(Content dataSource, String fileName, String parentName) throws TskCoreException { + return caseDb.findFiles(dataSource, fileName, parentName); } /** - * Finds a set of localFiles that meets the name criteria. + * Finds all files and directories with a given file name and given parent + * file or directory in a given data source (image, local/logical files set, + * etc.). The name search is for full or partial matches and is case + * insensitive (a case insensitive SQL LIKE clause is used to query the case + * database). * - * @param dataSource Root data source to limit search results to (Image, - * VirtualDirectory, etc.). - * @param fileName Pattern of the name of the file or directory to match - * (case insensitive, used in LIKE SQL statement). - * @param parentFile Object of root/parent directory to restrict search to. + * @param dataSource The data source. + * @param fileName The full or partial file name. + * @param parent The parent file or directory. * - * @return a list of AbstractFile for localFiles/directories whose name - * matches fileName and that were inside a directory described by - * parentFsContent. + * @return The matching files and directories. + * + * @throws TskCoreException if there is a problem querying the case + * database. */ - public synchronized List findFiles(Content dataSource, String fileName, AbstractFile parentFile) throws TskCoreException { - if (tskCase == null) { - throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles3.exception.msg")); - } - return findFiles(dataSource, fileName, parentFile.getName()); + public synchronized List findFiles(Content dataSource, String fileName, AbstractFile parent) throws TskCoreException { + return findFiles(dataSource, fileName, parent.getName()); } /** @@ -221,175 +241,120 @@ public class FileManager implements Closeable { * * @return a list of AbstractFile that have the given file path. */ + /** + * Finds all files and directories with a given file name and path in a + * given data source (image, local/logical files set, etc.). The name search + * is for full or partial matches and is case insensitive (a case + * insensitive SQL LIKE clause is used to query the case database). Any path + * components at the volume level and above are removed for the search. + * + * @param dataSource The data source. + * @param fileName The full or partial file name. + * @param filePath The file path (path components volume at the volume + * level or above will be removed). + * + * @return The matching files and directories. + * + * @throws TskCoreException if there is a problem querying the case + * database. + */ public synchronized List openFiles(Content dataSource, String filePath) throws TskCoreException { - if (tskCase == null) { - throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.openFiles.exception.msg")); + if (null == caseDb) { + throw new TskCoreException("FileManager closed"); } - return tskCase.openFiles(dataSource, filePath); + return caseDb.openFiles(dataSource, filePath); } /** - * Creates a derived file, adds it to the database and returns it. + * Adds a derived file to the case. * - * @param fileName file name the derived file - * @param localPath local path of the derived file, including the file - * name. The path is relative to the case folder. - * @param size size of the derived file in bytes - * @param ctime - * @param crtime - * @param atime - * @param mtime - * @param isFile whether a file or directory, true if a file - * @param parentFile the parent file object this the new file was - * derived from, either a fs file or parent derived - * file/dikr\\r - * @param rederiveDetails details needed to re-derive file (will be specific - * to the derivation method), currently unused - * @param toolName name of derivation method/tool, currently unused - * @param toolVersion version of derivation method/tool, currently - * unused - * @param otherDetails details of derivation method/tool, currently - * unused + * @param fileName The name of the file. + * @param localPath The local path of the file, relative to the case + * folder and including the file name. + * @param size The size of the file in bytes. + * @param ctime The change time of the file. + * @param crtime The create time of the file + * @param atime The accessed time of the file. + * @param mtime The modified time of the file. + * @param isFile True if a file, false if a directory. + * @param parentFile The parent file from which the file was derived. + * @param rederiveDetails The details needed to re-derive file (will be + * specific to the derivation method), currently + * unused. + * @param toolName The name of the derivation method or tool, + * currently unused. + * @param toolVersion The version of the derivation method or tool, + * currently unused. + * @param otherDetails Other details of the derivation method or tool, + * currently unused. * - * @return newly created derived file object added to the database - * - * @throws TskCoreException exception thrown if the object creation failed - * due to a critical system error or of the file - * manager has already been closed + * @return A DerivedFile object representing the derived file. * + * @throws TskCoreException if there is a problem adding the file to the + * case database. */ - public synchronized DerivedFile addDerivedFile(String fileName, String localPath, long size, + public synchronized DerivedFile addDerivedFile(String fileName, + String localPath, + long size, long ctime, long crtime, long atime, long mtime, - boolean isFile, AbstractFile parentFile, + boolean isFile, + AbstractFile parentFile, String rederiveDetails, String toolName, String toolVersion, String otherDetails) throws TskCoreException { - - if (tskCase == null) { - throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.addDerivedFile.exception.msg")); - } - - return tskCase.addDerivedFile(fileName, localPath, size, + return caseDb.addDerivedFile(fileName, localPath, size, ctime, crtime, atime, mtime, isFile, parentFile, rederiveDetails, toolName, toolVersion, otherDetails); } /** - * Adds a carved file to the VirtualDirectory '$CarvedFiles' in the volume - * or image given by systemId. + * Adds a carved file to the '$CarvedFiles' virtual directory of a data + * source, volume or file system. * - * @param carvedFileName the name of the carved file (containing appropriate - * extension) - * @param carvedFileSize size of the carved file to add - * @param systemId the ID of the parent volume or file system - * @param sectors a list of SectorGroups giving this sectors that - * make up this carved file. + * @param fileName The name of the file. + * @param fileSize The size of the file. + * @param parentObjId The object id of the parent data source, volume or + * file system. + * @param layout A list of the offsets and sizes that gives the layout + * of the file within its parent. * - * @throws TskCoreException exception thrown when critical tsk error - * occurred and carved file could not be added + * @return A LayoutFile object representing the carved file. + * + * @throws TskCoreException if there is a problem adding the file to the + * case database. */ - public synchronized LayoutFile addCarvedFile(String carvedFileName, long carvedFileSize, - long systemId, List sectors) throws TskCoreException { - - if (tskCase == null) { - throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.addCarvedFile.exception.msg")); - } - - return tskCase.addCarvedFile(carvedFileName, carvedFileSize, systemId, sectors); + public synchronized LayoutFile addCarvedFile(String fileName, long fileSize, long parentObjId, List layout) throws TskCoreException { + return caseDb.addCarvedFile(fileName, fileSize, parentObjId, layout); } /** - * Adds a collection of carved localFiles to the VirtualDirectory - * '$CarvedFiles' in the volume or image given by systemId. Creates - * $CarvedFiles if it does not exist already. + * Adds a collection of carved files to the '$CarvedFiles' virtual directory + * of a data source, volume or file system. * - * @param filesToAdd a list of CarvedFileContainer localFiles to add as - * carved localFiles + * @param A collection of CarvedFileContainer objects, one per carved file, + * all of which must have the same parent object id. * - * @return List This is a list of the localFiles added to the - * database + * @return A collection of LayoutFile object representing the carved files. * - * @throws org.sleuthkit.datamodel.TskCoreException + * @throws TskCoreException if there is a problem adding the files to the + * case database. */ public List addCarvedFiles(List filesToAdd) throws TskCoreException { - if (tskCase == null) { - throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.addCarvedFile.exception.msg")); - } else { - return tskCase.addCarvedFiles(filesToAdd); - } + return caseDb.addCarvedFiles(filesToAdd); } /** - * - * Interface for receiving notifications on folders being added via a - * callback + * Interface for receiving a notification for each file or directory added + * to the case database by a FileManager add files operation. */ public interface FileAddProgressUpdater { /** - * Called when new folders has been added + * Called after a file or directory is added to the case database. * - * @param newFile the file/folder added to the Case + * @param An AbstractFile represeting the added file or directory. */ public void fileAdded(AbstractFile newFile); } - /** - * Add a set of local/logical localFiles and dirs. - * - * @param localAbsPaths list of absolute paths to local localFiles and - * dirs - * @param addProgressUpdater notifier to receive progress notifications on - * folders added, or null if not used - * - * @return file set root VirtualDirectory contained containing all - * AbstractFile objects added - * - * @throws TskCoreException exception thrown if the object creation failed - * due to a critical system error or of the file - * manager has already been closed. There is no - * "revert" logic if one of the additions fails. - * The addition stops with the first error - * encountered. - */ - public synchronized VirtualDirectory addLocalFilesDirs(List localAbsPaths, FileAddProgressUpdater addProgressUpdater) throws TskCoreException { - List rootsToAdd; - try { - rootsToAdd = getFilesAndDirectories(localAbsPaths); - } catch (TskDataException ex) { - throw new TskCoreException(ex.getLocalizedMessage(), ex); - } - - CaseDbTransaction trans = tskCase.beginTransaction(); - // make a virtual top-level directory for this set of localFiles/dirs - final VirtualDirectory fileSetRootDir = addLocalFileSetRootDir(trans); - - try { - // recursively add each item in the set - for (java.io.File localRootToAdd : rootsToAdd) { - AbstractFile localFileAdded = addLocalDirInt(trans, fileSetRootDir, localRootToAdd, addProgressUpdater); - - if (localFileAdded == null) { - String msg = NbBundle - .getMessage(this.getClass(), "FileManager.addLocalFilesDirs.exception.cantAdd.msg", - localRootToAdd.getAbsolutePath()); - logger.log(Level.SEVERE, msg); - throw new TskCoreException(msg); - } else { - //added.add(localFileAdded); - //send new content event - //for now reusing ingest events, in future this will be replaced by datamodel / observer sending out events - // @@@ Is this the right place for this? A directory tree refresh will be triggered, so this may be creating a race condition - // since the transaction is not yet committed. - IngestServices.getInstance().fireModuleContentEvent(new ModuleContentEvent(localFileAdded)); - } - } - - trans.commit(); - } catch (TskCoreException ex) { - trans.rollback(); - } - return fileSetRootDir; - } - /** * Adds a set of local/logical files and/or directories to the case database * as data source. @@ -419,20 +384,33 @@ public class FileManager implements Closeable { * directory that does not exist or cannot be read. */ public synchronized LocalFilesDataSource addLocalFilesDataSource(String deviceId, String rootVirtualDirectoryName, String timeZone, List localFilePaths, FileAddProgressUpdater progressUpdater) throws TskCoreException, TskDataException { + /* + * Convert the local/logical file paths into File objects. + */ List localFiles = getFilesAndDirectories(localFilePaths); CaseDbTransaction trans = null; try { + /* + * Generate a name for the root virtual directory for the data + * source, if a name was not supplied, and increment the counter + * used to generate the default names. + */ + int newLocalFilesSetCount = localFileDataSourcesCounter + 1; String rootDirectoryName = rootVirtualDirectoryName; - int newLocalFilesSetCount = curNumFileSets + 1; if (rootVirtualDirectoryName.isEmpty()) { rootDirectoryName = VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX + newLocalFilesSetCount; } - trans = tskCase.beginTransaction(); - LocalFilesDataSource dataSource = tskCase.addLocalFilesDataSource(deviceId, rootDirectoryName, timeZone, trans); + + /* + * Add the root virtual directory and its local/logical file + * chioldren to the case database. + */ + trans = caseDb.beginTransaction(); + LocalFilesDataSource dataSource = caseDb.addLocalFilesDataSource(deviceId, rootDirectoryName, timeZone, trans); VirtualDirectory rootDirectory = dataSource.getRootDirectory(); List filesAdded = new ArrayList<>(); for (java.io.File localFile : localFiles) { - AbstractFile fileAdded = addLocalDirInt(trans, rootDirectory, localFile, progressUpdater); + AbstractFile fileAdded = addLocalFile(trans, rootDirectory, localFile, progressUpdater); if (null != fileAdded) { filesAdded.add(fileAdded); } else { @@ -440,13 +418,28 @@ public class FileManager implements Closeable { } } trans.commit(); + + /* + * Update the counter used to generate the default names. + * + * TODO (AUT-1905): Although the counter is guarded by the monitor + * of the FileManager, this does not guarantee unique default file + * set names for multi-user cases where multiple nodes can be + * running FileManagers for the same case. + */ if (rootVirtualDirectoryName.isEmpty()) { - curNumFileSets = newLocalFilesSetCount; + localFileDataSourcesCounter = newLocalFilesSetCount; } + + /* + * Publish content added events for the added files and directories. + */ for (AbstractFile fileAdded : filesAdded) { IngestServices.getInstance().fireModuleContentEvent(new ModuleContentEvent(fileAdded)); } + return dataSource; + } catch (TskCoreException ex) { if (null != trans) { trans.rollback(); @@ -472,7 +465,7 @@ public class FileManager implements Closeable { for (String path : localFilePaths) { java.io.File localFile = new java.io.File(path); if (!localFile.exists() || !localFile.canRead()) { - throw new TskDataException(NbBundle.getMessage(this.getClass(), "FileManager.addLocalFilesDirs.exception.notReadable.msg", localFile.getAbsolutePath())); + throw new TskDataException(String.format("File at %s does not exist or cannot be read", localFile.getAbsolutePath())); } localFiles.add(localFile); } @@ -480,130 +473,96 @@ public class FileManager implements Closeable { } /** - * Adds a new virtual directory root object with FileSet X name and - * consecutive sequence number characteristic to every add operation - * - * @return the virtual dir root container created - * - * @throws TskCoreException - */ - private VirtualDirectory addLocalFileSetRootDir(CaseDbTransaction trans) throws TskCoreException { - - VirtualDirectory created = null; - - int newFileSetCount = curNumFileSets + 1; - final String fileSetName = VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX + newFileSetCount; - - try { - created = tskCase.addVirtualDirectory(0, fileSetName, trans); - curNumFileSets = newFileSetCount; - } catch (TskCoreException ex) { - String msg = NbBundle - .getMessage(this.getClass(), "FileManager.addLocalFileSetRootDir.exception.errCreateDir.msg", - fileSetName); - logger.log(Level.SEVERE, msg, ex); - throw new TskCoreException(msg, ex); - } - - return created; - } - - /** - * Helper (internal) method to recursively add contents of a folder. Node - * passed in can be a file or directory. Children of directories are added. + * Adds a file or directory of logical/local files data source to the case + * database, recursively adding the contents of directories. * * @param trans A case database transaction. - * @param parentVd Dir that is the parent of localFile - * @param localFile File/Dir that we are adding + * @param parentDirectory The root virtual direcotry of the data source. + * @param localFile The local/logical file or directory. * @param addProgressUpdater notifier to receive progress notifications on * folders added, or null if not used * * @returns File object of file added or new virtualdirectory for the * directory. - * @throws TskCoreException + * @param progressUpdater Called after each file/directory is added to + * the case database. + * + * @return An AbstractFile representation of the local/logical file. + * + * @throws TskCoreException If there is a problem completing a database + * operation. */ - private AbstractFile addLocalDirInt(CaseDbTransaction trans, VirtualDirectory parentVd, - java.io.File localFile, FileAddProgressUpdater addProgressUpdater) throws TskCoreException { - - if (tskCase == null) { - throw new TskCoreException( - NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt.exception.closed.msg")); - } - - //final String localName = localDir.getName(); - if (!localFile.exists()) { - throw new TskCoreException( - NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt.exception.doesntExist.msg", - localFile.getAbsolutePath())); - } - if (!localFile.canRead()) { - throw new TskCoreException( - NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt.exception.notReadable.msg", - localFile.getAbsolutePath())); - } - + private AbstractFile addLocalFile(CaseDbTransaction trans, VirtualDirectory parentDirectory, java.io.File localFile, FileAddProgressUpdater progressUpdater) throws TskCoreException { if (localFile.isDirectory()) { - //create virtual folder (we don't have a notion of a 'local folder') - final VirtualDirectory childVd = tskCase.addVirtualDirectory(parentVd.getId(), localFile.getName(), trans); - if (childVd != null && addProgressUpdater != null) { - addProgressUpdater.fileAdded(childVd); - } - //add children recursively - final java.io.File[] childrenFiles = localFile.listFiles(); - if (childrenFiles != null) { - for (java.io.File childFile : childrenFiles) { - addLocalDirInt(trans, childVd, childFile, addProgressUpdater); + /* + * Add the directory as a virtual directory. + */ + VirtualDirectory virtualDirectory = caseDb.addVirtualDirectory(parentDirectory.getId(), localFile.getName(), trans); + progressUpdater.fileAdded(virtualDirectory); + + /* + * Add its children, if any. + */ + final java.io.File[] childFiles = localFile.listFiles(); + if (childFiles != null && childFiles.length > 0) { + for (java.io.File childFile : childFiles) { + addLocalFile(trans, virtualDirectory, childFile, progressUpdater); } } - return childVd; + + return virtualDirectory; } else { - //add leaf file, base case - return this.addLocalFileInt(parentVd, localFile, trans); + return caseDb.addLocalFile(localFile.getName(), localFile.getAbsolutePath(), localFile.length(), + 0, 0, 0, 0, + localFile.isFile(), parentDirectory, trans); } } - /** - * Adds a single local/logical file to the case. Adds it to the database. - * Does not refresh the views of data. Assumes that the local file exists - * and can be read. This checking is done by addLocalDirInt(). - * - * @param parentFile parent file object container (such as virtual - * directory, another local file, or fscontent File), - * @param localFile File that we are adding - * @param trans A case database transaction. - * - * @return newly created local file object added to the database - * - * @throws TskCoreException exception thrown if the object creation failed - * due to a critical system error or of the file - * manager has already been closed - */ - private synchronized LocalFile addLocalFileInt(AbstractFile parentFile, java.io.File localFile, CaseDbTransaction trans) throws TskCoreException { - - if (tskCase == null) { - throw new TskCoreException( - NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt2.exception.closed.msg")); - } - - long size = localFile.length(); - boolean isFile = localFile.isFile(); - - long ctime = 0; - long crtime = 0; - long atime = 0; - long mtime = 0; - - String fileName = localFile.getName(); - - LocalFile lf = tskCase.addLocalFile(fileName, localFile.getAbsolutePath(), size, - ctime, crtime, atime, mtime, - isFile, parentFile, trans); - - return lf; - } - @Override public synchronized void close() throws IOException { - tskCase = null; + caseDb = null; } + + /** + * Contructs a case-level service that provides management of files within + * the data sources added to a case and the local files associated with a + * case. + * + * @param tskCase The case database. + * + * @deprecated Use Case.getCurrentCase().getServices().getFileManager() + * instead. + */ + @Deprecated + public FileManager(SleuthkitCase tskCase) { + this(); + } + + /** + * Adds a set of local/logical files and/or directories to the case database + * as data source. + * + * @param localFilePaths A list of local/logical file and/or directory + * localFilePaths. + * @param progressUpdater Called after each file/directory is added to the + * case database. + * + * @return The root virtual directory for the local/logical files data + * source. + * + * @throws TskCoreException If any of the local file paths is for a file or + * directory that does not exist or cannot be read, + * or there is a problem completing a database + * operation. + * @deprecated Use addLocalFilesDataSource instead. + */ + @Deprecated + public synchronized VirtualDirectory addLocalFilesDirs(List localFilePaths, FileAddProgressUpdater progressUpdater) throws TskCoreException { + try { + return addLocalFilesDataSource("", "", "", localFilePaths, progressUpdater).getRootDirectory(); + } catch (TskDataException ex) { + throw new TskCoreException(ex.getLocalizedMessage(), ex); + } + } + } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java index 880bc8008e..3106d7c3f7 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java @@ -2,7 +2,7 @@ * * Autopsy Forensic Browser * - * Copyright 2012-2015 Basis Technology Corp. + * Copyright 2012-2016 Basis Technology Corp. * * Copyright 2012 42six Solutions. * Contact: aebadirad 42six com @@ -29,6 +29,7 @@ import java.util.List; import org.openide.util.Lookup; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.autopsy.casemodule.Case; /** * A class to manage various services. @@ -41,6 +42,20 @@ public class Services implements Closeable { private final KeywordSearchService keywordSearchService; private final Blackboard blackboard; + Services(Case currentCase, SleuthkitCase caseDb) { + fileManager = new FileManager(currentCase, caseDb); + services.add(fileManager); + + tagsManager = new TagsManager(caseDb); + services.add(tagsManager); + + keywordSearchService = Lookup.getDefault().lookup(KeywordSearchService.class); + services.add(keywordSearchService); + + blackboard = new Blackboard(); + services.add(blackboard); + } + public Services(SleuthkitCase tskCase) { fileManager = new FileManager(tskCase); services.add(fileManager); From f746f455c85f23d9aa7d7b5d4b4253ed6ec16f99 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Fri, 27 May 2016 12:53:10 -0400 Subject: [PATCH 2/3] Complete docs/deprecation for FileManager API --- .../sleuthkit/autopsy/casemodule/Case.java | 2 + .../casemodule/services/Blackboard.java | 7 +- .../casemodule/services/FileManager.java | 211 ++++++++---------- .../autopsy/casemodule/services/Services.java | 78 ++++--- .../casemodule/services/TagsManager.java | 56 ++--- .../KeywordSearchService.java | 8 +- 6 files changed, 178 insertions(+), 184 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 7677b5be68..ecd67d2052 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -282,6 +282,7 @@ public class Case implements SleuthkitCase.ErrorObserver { /** * Constructor for the Case class */ + @SuppressWarnings("deprecation") private Case(CaseMetadata caseMetadata, SleuthkitCase db) { this.caseMetadata = caseMetadata; this.db = db; @@ -835,6 +836,7 @@ public class Case implements SleuthkitCase.ErrorObserver { /** * Closes this case. This methods close the xml and clear all the fields. */ + @SuppressWarnings("deprecation") public void closeCase() throws CaseActionException { changeCase(null); try { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java index d5064e3b4e..1f2f4b252b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java @@ -109,10 +109,13 @@ public final class Blackboard implements Closeable { } /** - * Cloese this blackboard and releases any resources associated with it. - * @throws IOException + * Closes the blackboard. + * + * @throws IOException If there is a problem closing the blackboard. + * @deprecated File manager clients should not close the blackboard. */ @Override + @Deprecated public void close() throws IOException { } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java index 336e97742b..5bf85602d4 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java @@ -26,10 +26,8 @@ import java.io.Closeable; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.logging.Level; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; @@ -37,7 +35,6 @@ import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.DerivedFile; import org.sleuthkit.datamodel.LayoutFile; -import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction; import org.sleuthkit.datamodel.TskCoreException; @@ -48,55 +45,19 @@ import org.sleuthkit.datamodel.LocalFilesDataSource; import org.sleuthkit.datamodel.TskDataException; /** - * A case-level service that provides methods for retrieving files associated - * with the case and for adding local files, carved files, and derived files to - * the case. + * A manager that provides methods for retrieving files from the current case + * and for adding local files, carved files, and derived files to the current + * case. */ public class FileManager implements Closeable { - private static final Logger logger = Logger.getLogger(FileManager.class.getName()); - private SleuthkitCase caseDb; - - /* - * TODO (AUT-1905): Although this counter is guarded by the monitor of the - * FileManager, this does not guarantee unique default file set names for - * multi-user cases where multiple nodes can be running FileManagers for the - * same case. - */ - private int localFileDataSourcesCounter; - /** - * Constructs a case-level service that provides methods for retrieving - * files associated with the case and for adding local files, carved files, - * and derived files to the case. + * Constructs a manager that provides methods for retrieving files from the + * current case and for adding local files, carved files, and derived files + * to the current case. + * */ - FileManager(Case currentCase, SleuthkitCase caseDb) throws TskCoreException { - this.caseDb = caseDb; - initializeLocalFileDataSourcesCounter(); - } - - /** - * Initialize the counter for the number of logical/local file sets that is - * used to generate the default logical/local file data source names. - */ - private void initializeLocalFileDataSourcesCounter() { - /* - * TODO (AUT-1905): Although the counter is guarded by the monitor of - * the FileManager, this does not guarantee unique default file set - * names for multi-user cases where multiple nodes can be running - * FileManagers for the same case. - */ - localFileDataSourcesCounter = 0; - try { - List localFileDataSources = caseDb.getVirtualDirectoryRoots(); - for (VirtualDirectory vd : localFileDataSources) { - if (vd.getName().startsWith(VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX)) { - ++localFileDataSourcesCounter; - } - } - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error initializing logical files counter", ex); //NON-NLS - } + FileManager() { } /** @@ -111,12 +72,9 @@ public class FileManager implements Closeable { * @throws TskCoreException if there is a problem querying the case * database. */ - public synchronized List findFiles(String fileName) throws TskCoreException { - if (null == caseDb) { - throw new TskCoreException("FileManager closed"); - } + public List findFiles(String fileName) throws TskCoreException { List result = new ArrayList<>(); - List dataSources = caseDb.getRootObjects(); + List dataSources = Case.getCurrentCase().getSleuthkitCase().getRootObjects(); for (Content dataSource : dataSources) { result.addAll(findFiles(dataSource, fileName)); } @@ -137,12 +95,9 @@ public class FileManager implements Closeable { * @throws TskCoreException if there is a problem querying the case * database. */ - public synchronized List findFiles(String fileName, String parentName) throws TskCoreException { - if (null == caseDb) { - throw new TskCoreException("FileManager closed"); - } + public List findFiles(String fileName, String parentName) throws TskCoreException { List result = new ArrayList<>(); - List dataSources = caseDb.getRootObjects(); + List dataSources = Case.getCurrentCase().getSleuthkitCase().getRootObjects(); for (Content dataSource : dataSources) { result.addAll(findFiles(dataSource, fileName, parentName)); } @@ -163,12 +118,9 @@ public class FileManager implements Closeable { * @throws TskCoreException if there is a problem querying the case * database. */ - public synchronized List findFiles(String fileName, AbstractFile parent) throws TskCoreException { - if (null == caseDb) { - throw new TskCoreException("FileManager closed"); - } + public List findFiles(String fileName, AbstractFile parent) throws TskCoreException { List result = new ArrayList<>(); - List dataSources = caseDb.getRootObjects(); + List dataSources = Case.getCurrentCase().getSleuthkitCase().getRootObjects(); for (Content dataSource : dataSources) { result.addAll(findFiles(dataSource, fileName, parent)); } @@ -189,8 +141,8 @@ public class FileManager implements Closeable { * @throws TskCoreException if there is a problem querying the case * database. */ - public synchronized List findFiles(Content dataSource, String fileName) throws TskCoreException { - return caseDb.findFiles(dataSource, fileName); + public List findFiles(Content dataSource, String fileName) throws TskCoreException { + return Case.getCurrentCase().getSleuthkitCase().findFiles(dataSource, fileName); } /** @@ -209,8 +161,8 @@ public class FileManager implements Closeable { * @throws TskCoreException if there is a problem querying the case * database. */ - public synchronized List findFiles(Content dataSource, String fileName, String parentName) throws TskCoreException { - return caseDb.findFiles(dataSource, fileName, parentName); + public List findFiles(Content dataSource, String fileName, String parentName) throws TskCoreException { + return Case.getCurrentCase().getSleuthkitCase().findFiles(dataSource, fileName, parentName); } /** @@ -229,7 +181,7 @@ public class FileManager implements Closeable { * @throws TskCoreException if there is a problem querying the case * database. */ - public synchronized List findFiles(Content dataSource, String fileName, AbstractFile parent) throws TskCoreException { + public List findFiles(Content dataSource, String fileName, AbstractFile parent) throws TskCoreException { return findFiles(dataSource, fileName, parent.getName()); } @@ -258,11 +210,8 @@ public class FileManager implements Closeable { * @throws TskCoreException if there is a problem querying the case * database. */ - public synchronized List openFiles(Content dataSource, String filePath) throws TskCoreException { - if (null == caseDb) { - throw new TskCoreException("FileManager closed"); - } - return caseDb.openFiles(dataSource, filePath); + public List openFiles(Content dataSource, String filePath) throws TskCoreException { + return Case.getCurrentCase().getSleuthkitCase().openFiles(dataSource, filePath); } /** @@ -293,14 +242,15 @@ public class FileManager implements Closeable { * @throws TskCoreException if there is a problem adding the file to the * case database. */ - public synchronized DerivedFile addDerivedFile(String fileName, + public DerivedFile addDerivedFile(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime, boolean isFile, AbstractFile parentFile, String rederiveDetails, String toolName, String toolVersion, String otherDetails) throws TskCoreException { - return caseDb.addDerivedFile(fileName, localPath, size, + + return Case.getCurrentCase().getSleuthkitCase().addDerivedFile(fileName, localPath, size, ctime, crtime, atime, mtime, isFile, parentFile, rederiveDetails, toolName, toolVersion, otherDetails); } @@ -322,7 +272,7 @@ public class FileManager implements Closeable { * case database. */ public synchronized LayoutFile addCarvedFile(String fileName, long fileSize, long parentObjId, List layout) throws TskCoreException { - return caseDb.addCarvedFile(fileName, fileSize, parentObjId, layout); + return Case.getCurrentCase().getSleuthkitCase().addCarvedFile(fileName, fileSize, parentObjId, layout); } /** @@ -338,7 +288,7 @@ public class FileManager implements Closeable { * case database. */ public List addCarvedFiles(List filesToAdd) throws TskCoreException { - return caseDb.addCarvedFiles(filesToAdd); + return Case.getCurrentCase().getSleuthkitCase().addCarvedFiles(filesToAdd); } /** @@ -352,7 +302,7 @@ public class FileManager implements Closeable { * * @param An AbstractFile represeting the added file or directory. */ - public void fileAdded(AbstractFile newFile); + void fileAdded(AbstractFile newFile); } /** @@ -384,27 +334,19 @@ public class FileManager implements Closeable { * directory that does not exist or cannot be read. */ public synchronized LocalFilesDataSource addLocalFilesDataSource(String deviceId, String rootVirtualDirectoryName, String timeZone, List localFilePaths, FileAddProgressUpdater progressUpdater) throws TskCoreException, TskDataException { - /* - * Convert the local/logical file paths into File objects. - */ List localFiles = getFilesAndDirectories(localFilePaths); CaseDbTransaction trans = null; try { - /* - * Generate a name for the root virtual directory for the data - * source, if a name was not supplied, and increment the counter - * used to generate the default names. - */ - int newLocalFilesSetCount = localFileDataSourcesCounter + 1; String rootDirectoryName = rootVirtualDirectoryName; - if (rootVirtualDirectoryName.isEmpty()) { - rootDirectoryName = VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX + newLocalFilesSetCount; + if (rootDirectoryName.isEmpty()) { + rootDirectoryName = generateFilesDataSourceName(); } /* * Add the root virtual directory and its local/logical file - * chioldren to the case database. + * children to the case database. */ + SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase(); trans = caseDb.beginTransaction(); LocalFilesDataSource dataSource = caseDb.addLocalFilesDataSource(deviceId, rootDirectoryName, timeZone, trans); VirtualDirectory rootDirectory = dataSource.getRootDirectory(); @@ -419,18 +361,6 @@ public class FileManager implements Closeable { } trans.commit(); - /* - * Update the counter used to generate the default names. - * - * TODO (AUT-1905): Although the counter is guarded by the monitor - * of the FileManager, this does not guarantee unique default file - * set names for multi-user cases where multiple nodes can be - * running FileManagers for the same case. - */ - if (rootVirtualDirectoryName.isEmpty()) { - localFileDataSourcesCounter = newLocalFilesSetCount; - } - /* * Publish content added events for the added files and directories. */ @@ -448,6 +378,34 @@ public class FileManager implements Closeable { } } + /** + * Generates a name for the root virtual directory for the data source. + * + * NOTE: Although this method is guarded by the file manager's monitor, + * there is currently a minimal chance of default name duplication for + * multi-user cases with multiple FileManagers running on different nodes. + * + * @return A default name for a local/logical files data source of the form: + * LogicalFileSet[N]. + * + * @throws TskCoreException If there is a problem querying the case + * database. + */ + private synchronized String generateFilesDataSourceName() throws TskCoreException { + int localFileDataSourcesCounter = 0; + try { + List localFileDataSources = Case.getCurrentCase().getSleuthkitCase().getVirtualDirectoryRoots(); + for (VirtualDirectory vd : localFileDataSources) { + if (vd.getName().startsWith(VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX)) { + ++localFileDataSourcesCounter; + } + } + return VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX + (localFileDataSourcesCounter + 1); + } catch (TskCoreException ex) { + throw new TskCoreException("Error querying for existing local file data sources with defualt names", ex); + } + } + /** * Converts a list of local/logical file and/or directory paths to a list of * file objects. @@ -497,7 +455,7 @@ public class FileManager implements Closeable { /* * Add the directory as a virtual directory. */ - VirtualDirectory virtualDirectory = caseDb.addVirtualDirectory(parentDirectory.getId(), localFile.getName(), trans); + VirtualDirectory virtualDirectory = Case.getCurrentCase().getSleuthkitCase().addVirtualDirectory(parentDirectory.getId(), localFile.getName(), trans); progressUpdater.fileAdded(virtualDirectory); /* @@ -512,32 +470,12 @@ public class FileManager implements Closeable { return virtualDirectory; } else { - return caseDb.addLocalFile(localFile.getName(), localFile.getAbsolutePath(), localFile.length(), + return Case.getCurrentCase().getSleuthkitCase().addLocalFile(localFile.getName(), localFile.getAbsolutePath(), localFile.length(), 0, 0, 0, 0, localFile.isFile(), parentDirectory, trans); } } - @Override - public synchronized void close() throws IOException { - caseDb = null; - } - - /** - * Contructs a case-level service that provides management of files within - * the data sources added to a case and the local files associated with a - * case. - * - * @param tskCase The case database. - * - * @deprecated Use Case.getCurrentCase().getServices().getFileManager() - * instead. - */ - @Deprecated - public FileManager(SleuthkitCase tskCase) { - this(); - } - /** * Adds a set of local/logical files and/or directories to the case database * as data source. @@ -557,7 +495,7 @@ public class FileManager implements Closeable { * @deprecated Use addLocalFilesDataSource instead. */ @Deprecated - public synchronized VirtualDirectory addLocalFilesDirs(List localFilePaths, FileAddProgressUpdater progressUpdater) throws TskCoreException { + public VirtualDirectory addLocalFilesDirs(List localFilePaths, FileAddProgressUpdater progressUpdater) throws TskCoreException { try { return addLocalFilesDataSource("", "", "", localFilePaths, progressUpdater).getRootDirectory(); } catch (TskDataException ex) { @@ -565,4 +503,29 @@ public class FileManager implements Closeable { } } + /** + * Constructs a manager that provides methods for retrieving files from the + * current case and for adding local files, carved files, and derived files + * to the current case. + * + * @param caseDb The case database. + * + * @deprecated Use Case.getCurrentCase().getServices().getFileManager() + * instead. + */ + @Deprecated + public FileManager(SleuthkitCase caseDb) { + } + + /** + * Closes the file manager. + * + * @throws IOException If there is a problem closing the file manager. + * @deprecated File manager clients should not close the file manager. + */ + @Override + @Deprecated + public void close() throws IOException { + } + } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java index 3106d7c3f7..1dbae18d68 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java @@ -1,19 +1,18 @@ /* * * Autopsy Forensic Browser - * - * Copyright 2012-2016 Basis Technology Corp. - * + * + * Copyright 2011-2016 Basis Technology Corp. + * Contact: carrier sleuthkit org * Copyright 2012 42six Solutions. * Contact: aebadirad 42six com - * Project Contact/Architect: carrier sleuthkit org - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -29,10 +28,10 @@ import java.util.List; import org.openide.util.Lookup; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.sleuthkit.datamodel.SleuthkitCase; -import org.sleuthkit.autopsy.casemodule.Case; /** - * A class to manage various services. + * A collection of case-level services (e.g., file manager, tags manager, + * keyword search, blackboard). */ public class Services implements Closeable { @@ -42,51 +41,76 @@ public class Services implements Closeable { private final KeywordSearchService keywordSearchService; private final Blackboard blackboard; - Services(Case currentCase, SleuthkitCase caseDb) { - fileManager = new FileManager(currentCase, caseDb); + /** + * Constructs a collection of case-level services (e.g., file manager, tags + * manager, keyword search, blackboard). + * + * @param caseDb The case database for the current case. + * + * @deprecated Use Case.getCurrentCase().getServices() instead. + * + * TODO (AUT-2158): Prevent public construction of the Services class. + */ + @Deprecated + public Services(SleuthkitCase caseDb) { + fileManager = new FileManager(); services.add(fileManager); - tagsManager = new TagsManager(caseDb); + tagsManager = new TagsManager(); services.add(tagsManager); keywordSearchService = Lookup.getDefault().lookup(KeywordSearchService.class); services.add(keywordSearchService); - - blackboard = new Blackboard(); - services.add(blackboard); - } - - public Services(SleuthkitCase tskCase) { - fileManager = new FileManager(tskCase); - services.add(fileManager); - tagsManager = new TagsManager(tskCase); - services.add(tagsManager); - - keywordSearchService = Lookup.getDefault().lookup(KeywordSearchService.class); - services.add(keywordSearchService); - blackboard = new Blackboard(); services.add(blackboard); } + /** + * Gets the file manager service for the current case. + * + * @return The file manager service for the current case. + */ public FileManager getFileManager() { return fileManager; } + /** + * Gets the tags manager service for the current case. + * + * @return The tags manager service for the current case. + */ public TagsManager getTagsManager() { return tagsManager; } + /** + * Gets the keyword search service for the current case. + * + * @return The keyword search service for the current case. + */ public KeywordSearchService getKeywordSearchService() { return keywordSearchService; } - + + /** + * Gets the blackboard service for the current case. + * + * @return The blackboard service for the current case. + */ public Blackboard getBlackboard() { return blackboard; } + /** + * Closes the services for the current case. + * + * @throws IOException if there is a problem closing the services. + * @deprecated Services clients other than the case should not close the + * services. + */ @Override + @Deprecated public void close() throws IOException { for (Closeable service : services) { service.close(); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index 963f54e51f..9da5e9fcbc 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -32,7 +32,6 @@ import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentTag; -import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; @@ -45,7 +44,6 @@ public class TagsManager implements Closeable { private static final Logger logger = Logger.getLogger(TagsManager.class.getName()); private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS - private final SleuthkitCase caseDb; private final HashMap uniqueTagNames = new HashMap<>(); private boolean tagNamesLoaded = false; @@ -53,11 +51,8 @@ public class TagsManager implements Closeable { * Constructs a per case Autopsy service that manages the creation, * updating, and deletion of tags applied to content and blackboard * artifacts by users. - * - * @param caseDb The case database for the current case. */ - TagsManager(SleuthkitCase caseDb) { - this.caseDb = caseDb; + TagsManager() { } /** @@ -71,7 +66,7 @@ public class TagsManager implements Closeable { */ public synchronized List getAllTagNames() throws TskCoreException { lazyLoadExistingTagNames(); - return caseDb.getAllTagNames(); + return Case.getCurrentCase().getSleuthkitCase().getAllTagNames(); } /** @@ -85,7 +80,7 @@ public class TagsManager implements Closeable { */ public synchronized List getTagNamesInUse() throws TskCoreException { lazyLoadExistingTagNames(); - return caseDb.getTagNamesInUse(); + return Case.getCurrentCase().getSleuthkitCase().getTagNamesInUse(); } /** @@ -159,7 +154,7 @@ public class TagsManager implements Closeable { /* * Add the tag name to the case. */ - TagName newTagName = caseDb.addTagName(displayName, description, color); + TagName newTagName = Case.getCurrentCase().getSleuthkitCase().addTagName(displayName, description, color); /* * Add the tag name to the tags settings. @@ -245,7 +240,7 @@ public class TagsManager implements Closeable { } } - tag = caseDb.addContentTag(content, tagName, comment, beginByteOffset, endByteOffset); + tag = Case.getCurrentCase().getSleuthkitCase().addContentTag(content, tagName, comment, beginByteOffset, endByteOffset); } try { @@ -267,7 +262,7 @@ public class TagsManager implements Closeable { public void deleteContentTag(ContentTag tag) throws TskCoreException { synchronized (this) { lazyLoadExistingTagNames(); - caseDb.deleteContentTag(tag); + Case.getCurrentCase().getSleuthkitCase().deleteContentTag(tag); } try { @@ -287,7 +282,7 @@ public class TagsManager implements Closeable { */ public synchronized List getAllContentTags() throws TskCoreException { lazyLoadExistingTagNames(); - return caseDb.getAllContentTags(); + return Case.getCurrentCase().getSleuthkitCase().getAllContentTags(); } /** @@ -302,7 +297,7 @@ public class TagsManager implements Closeable { */ public synchronized long getContentTagsCountByTagName(TagName tagName) throws TskCoreException { lazyLoadExistingTagNames(); - return caseDb.getContentTagsCountByTagName(tagName); + return Case.getCurrentCase().getSleuthkitCase().getContentTagsCountByTagName(tagName); } /** @@ -317,7 +312,7 @@ public class TagsManager implements Closeable { */ public synchronized ContentTag getContentTagByTagID(long tagID) throws TskCoreException { lazyLoadExistingTagNames(); - return caseDb.getContentTagByID(tagID); + return Case.getCurrentCase().getSleuthkitCase().getContentTagByID(tagID); } /** @@ -333,7 +328,7 @@ public class TagsManager implements Closeable { */ public synchronized List getContentTagsByTagName(TagName tagName) throws TskCoreException { lazyLoadExistingTagNames(); - return caseDb.getContentTagsByTagName(tagName); + return Case.getCurrentCase().getSleuthkitCase().getContentTagsByTagName(tagName); } /** @@ -349,7 +344,7 @@ public class TagsManager implements Closeable { */ public synchronized List getContentTagsByContent(Content content) throws TskCoreException { lazyLoadExistingTagNames(); - return caseDb.getContentTagsByContent(content); + return Case.getCurrentCase().getSleuthkitCase().getContentTagsByContent(content); } /** @@ -387,8 +382,8 @@ public class TagsManager implements Closeable { lazyLoadExistingTagNames(); if (null == comment) { throw new IllegalArgumentException("Passed null comment argument"); - } - tag = caseDb.addBlackboardArtifactTag(artifact, tagName, comment); + } + tag = Case.getCurrentCase().getSleuthkitCase().addBlackboardArtifactTag(artifact, tagName, comment); } try { @@ -410,7 +405,7 @@ public class TagsManager implements Closeable { public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException { synchronized (this) { lazyLoadExistingTagNames(); - caseDb.deleteBlackboardArtifactTag(tag); + Case.getCurrentCase().getSleuthkitCase().deleteBlackboardArtifactTag(tag); } try { @@ -430,7 +425,7 @@ public class TagsManager implements Closeable { */ public synchronized List getAllBlackboardArtifactTags() throws TskCoreException { lazyLoadExistingTagNames(); - return caseDb.getAllBlackboardArtifactTags(); + return Case.getCurrentCase().getSleuthkitCase().getAllBlackboardArtifactTags(); } /** @@ -446,7 +441,7 @@ public class TagsManager implements Closeable { */ public synchronized long getBlackboardArtifactTagsCountByTagName(TagName tagName) throws TskCoreException { lazyLoadExistingTagNames(); - return caseDb.getBlackboardArtifactTagsCountByTagName(tagName); + return Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifactTagsCountByTagName(tagName); } /** @@ -461,7 +456,7 @@ public class TagsManager implements Closeable { */ public synchronized BlackboardArtifactTag getBlackboardArtifactTagByTagID(long tagID) throws TskCoreException { lazyLoadExistingTagNames(); - return caseDb.getBlackboardArtifactTagByID(tagID); + return Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifactTagByID(tagID); } /** @@ -477,7 +472,7 @@ public class TagsManager implements Closeable { */ public synchronized List getBlackboardArtifactTagsByTagName(TagName tagName) throws TskCoreException { lazyLoadExistingTagNames(); - return caseDb.getBlackboardArtifactTagsByTagName(tagName); + return Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifactTagsByTagName(tagName); } /** @@ -493,13 +488,18 @@ public class TagsManager implements Closeable { */ public synchronized List getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact) throws TskCoreException { lazyLoadExistingTagNames(); - return caseDb.getBlackboardArtifactTagsByArtifact(artifact); + return Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifactTagsByArtifact(artifact); } /** - * Saves the avaialble tag names to secondary storage. + * Closes the tags manager, saving the avaialble tag names to secondary + * storage. + * + * @throws IOException If there is a problem closing the tags manager. + * @deprecated Tags manager clients should not close the tags manager. */ @Override + @Deprecated public synchronized void close() throws IOException { saveTagNamesToTagsSettings(); } @@ -524,7 +524,7 @@ public class TagsManager implements Closeable { */ private void addTagNamesFromCurrentCase() { try { - List currentTagNames = caseDb.getAllTagNames(); + List currentTagNames = Case.getCurrentCase().getSleuthkitCase().getAllTagNames(); for (TagName tagName : currentTagNames) { uniqueTagNames.put(tagName.getDisplayName(), tagName); } @@ -550,7 +550,7 @@ public class TagsManager implements Closeable { String[] tagNameAttributes = tagNameTuple.split(","); if (!uniqueTagNames.containsKey(tagNameAttributes[0])) { try { - TagName tagName = caseDb.addTagName(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.getColorByName(tagNameAttributes[2])); + TagName tagName = Case.getCurrentCase().getSleuthkitCase().addTagName(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.getColorByName(tagNameAttributes[2])); uniqueTagNames.put(tagName.getDisplayName(), tagName); } catch (TskCoreException ex) { Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to add saved tag name " + tagNameAttributes[0], ex); //NON-NLS @@ -566,7 +566,7 @@ public class TagsManager implements Closeable { private void addPredefinedTagNames() { if (!uniqueTagNames.containsKey(NbBundle.getMessage(this.getClass(), "TagsManager.predefTagNames.bookmark.text"))) { try { - TagName tagName = caseDb.addTagName( + TagName tagName = Case.getCurrentCase().getSleuthkitCase().addTagName( NbBundle.getMessage(this.getClass(), "TagsManager.predefTagNames.bookmark.text"), "", TagName.HTML_COLOR.NONE); uniqueTagNames.put(tagName.getDisplayName(), tagName); } catch (TskCoreException ex) { diff --git a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java index 69b7c57f4f..af43facec9 100644 --- a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java +++ b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,9 @@ import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.TskCoreException; /** - * + * An implementation of a keyword search service. + * + * TODO (AUT-2158: This interface should not extend Closeable. */ public interface KeywordSearchService extends Closeable { @@ -49,4 +51,4 @@ public interface KeywordSearchService extends Closeable { */ public void tryConnect(String host, int port) throws KeywordSearchServiceException; - } +} From 1e50ff8c982d7af361cdd43e3c45235001d2b46d Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Fri, 27 May 2016 13:01:29 -0400 Subject: [PATCH 3/3] Correct documentation for Blackboard class --- .../org/sleuthkit/autopsy/casemodule/services/Blackboard.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java index 1f2f4b252b..0b8b9aa8e1 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java @@ -112,7 +112,7 @@ public final class Blackboard implements Closeable { * Closes the blackboard. * * @throws IOException If there is a problem closing the blackboard. - * @deprecated File manager clients should not close the blackboard. + * @deprecated blackboard clients should not close the blackboard. */ @Override @Deprecated