Recursive local file support in FileManager and dir tree

This commit is contained in:
adam-m 2013-05-07 15:44:55 -04:00
parent e5c83bc9ce
commit ce4ee992ea
2 changed files with 134 additions and 38 deletions

View File

@ -25,7 +25,8 @@ package org.sleuthkit.autopsy.casemodule.services;
import java.io.Closeable;
import java.io.IOException;
import java.util.List;
import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.DerivedFile;
import org.sleuthkit.datamodel.FsContent;
@ -33,6 +34,7 @@ import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.VirtualDirectory;
/**
* Abstraction to facilitate access to files and directories.
@ -40,6 +42,7 @@ import org.sleuthkit.datamodel.TskCoreException;
public class FileManager implements Closeable {
private SleuthkitCase tskCase;
private static final Logger logger = Logger.getLogger(FileManager.class.getName());
public FileManager(SleuthkitCase tskCase) {
this.tskCase = tskCase;
@ -138,6 +141,90 @@ public class FileManager implements Closeable {
isFile, parentFile, rederiveDetails, toolName, toolVersion, otherDetails);
}
/**
* Helper (internal) to add child of local dir recursively
* @param parentVd
* @param childLocalFile
* @throws TskCoreException
*/
private void addLocalDirectoryRecInt(VirtualDirectory parentVd,
java.io.File childLocalFile) throws TskCoreException {
final boolean isDir = childLocalFile.isDirectory();
if (isDir) {
//create virtual folder
final VirtualDirectory childVd = tskCase.addVirtualDirectory(parentVd.getId(), childLocalFile.getName());
//add children recursively
for (java.io.File childChild : childLocalFile.listFiles()) {
addLocalDirectoryRecInt(childVd, childChild);
}
} else {
//add leaf file, base case
this.addLocalFileSingle(childLocalFile.getAbsolutePath(), parentVd);
}
}
/**
* Add a local directory and its children recursively.
*
*
* @param localAbsPath local absolute path of root folder whose children are
* to be added recursively
* @return parent virtual directory folder created representing the
* localAbsPath node
* @throws TskCoreException exception thrown if the object creation failed
* due to a critical system error or of the file manager has already been
* closed, or if the localAbsPath could not be accessed
*/
public synchronized VirtualDirectory addLocalDir(String localAbsPath) throws TskCoreException {
if (tskCase == null) {
throw new TskCoreException("Attempted to use FileManager after it was closed.");
}
java.io.File localDir = new java.io.File(localAbsPath);
if (!localDir.exists()) {
throw new TskCoreException("Attempted to add a local dir that does not exist: " + localAbsPath);
}
if (!localDir.canRead()) {
throw new TskCoreException("Attempted to add a local dir that is not readable: " + localAbsPath);
}
if (!localDir.isDirectory()) {
throw new TskCoreException("Attempted to add a local dir that is not a directory: " + localAbsPath);
}
final String rootVdName = localDir.getName();
VirtualDirectory rootVd = null;
try {
final long localFilesRootId = tskCase.getLocalFilesRootDirectoryId();
rootVd = tskCase.addVirtualDirectory(localFilesRootId, rootVdName);
} catch (TskCoreException e) {
//log and rethrow
final String msg = "Error creating root dir for local dir to be added, can't addLocalDir: " + localDir;
logger.log(Level.SEVERE, msg, e);
throw new TskCoreException(msg);
}
try {
java.io.File[] localChildren = localDir.listFiles();
for (java.io.File localChild : localChildren) {
//add childrnen recursively, at a time in separate transaction
//consider a single transaction for everything
addLocalDirectoryRecInt(rootVd, localChild);
}
} catch (TskCoreException e) {
final String msg = "Error creating local children for local dir to be added, can't fully add addLocalDir: " + localDir;
logger.log(Level.SEVERE, msg, e);
throw new TskCoreException(msg);
}
return rootVd;
}
/**
* Creates a single local file under $LocalFiles for the case, adds it to
* the database and returns it.
@ -147,7 +234,7 @@ public class FileManager implements Closeable {
* @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
* closed, or if the localAbsPath could not be accessed
*
*/
public synchronized LocalFile addLocalFileSingle(String localAbsPath) throws TskCoreException {
@ -203,8 +290,8 @@ public class FileManager implements Closeable {
isFile, parentFile);
//refresh the content tree
//TODO decouple, use Node autorefresh once implemented
DirectoryTreeTopComponent.getDefault().refreshContentTreeSafe();
//TODO decouple at least using events, and later use Node autorefresh once implemented
//DirectoryTreeTopComponent.getDefault().refreshContentTreeSafe();
return lf;
}

View File

@ -25,11 +25,13 @@ import org.openide.nodes.Children;
import org.sleuthkit.autopsy.datamodel.DirectoryNode;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
import org.sleuthkit.autopsy.datamodel.LocalFileNode;
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
import org.sleuthkit.autopsy.datamodel.LocalFileNode;
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
import org.sleuthkit.autopsy.datamodel.VolumeNode;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
@ -37,6 +39,7 @@ import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.datamodel.VirtualDirectory;
import org.sleuthkit.datamodel.Volume;
/**
@ -123,7 +126,11 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
try {
for (Content c : vol.getChildren()) {
if (!(c instanceof LayoutFile)) {
if (!(c instanceof LayoutFile
|| c instanceof VirtualDirectory
)
) {
ret = false;
break;
}
@ -173,14 +180,13 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
return isLeafDirectory(dn);
}
@Override
public Boolean visit(FileNode fn) {
private Boolean visitDeep(AbstractAbstractFileNode node) {
//is a leaf if has no children, or children are files not dirs
boolean hasChildren = fn.hasContentChildren();
boolean hasChildren = node.hasContentChildren();
if (!hasChildren) {
return true;
}
List<Content> derivedChildren = fn.getContentChildren();
List<Content> derivedChildren = node.getContentChildren();
//child of a file, must be a (derived) file too
for (Content childContent : derivedChildren) {
if (((AbstractFile) childContent).isDir()) {
@ -200,34 +206,32 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
}
@Override
public Boolean visit(LocalFileNode dfn) {
//is a leaf if has no children, or children are files not dirs
boolean hasChildren = dfn.hasContentChildren();
if (!hasChildren) {
return true;
}
List<Content> derivedChildren = dfn.getContentChildren();
//child of a file, must be a (derived) file too
for (Content childContent : derivedChildren) {
if (((AbstractFile) childContent).isDir()) {
return false;
} else {
try {
if (childContent.hasChildren()) {
return false;
}
} catch (TskCoreException e) {
logger.log(Level.SEVERE, "Error checking if derived file node is leaf.", e);
}
}
}
return true;
public Boolean visit(FileNode fn) {
return visitDeep(fn);
}
@Override
public Boolean visit(LocalFileNode lfn) {
return visitDeep(lfn);
}
@Override
public Boolean visit(LayoutFileNode fn) {
return visitDeep(fn);
}
@Override
public Boolean visit(VolumeNode vn) {
return isLeafVolume(vn);
}
@Override
public Boolean visit(VirtualDirectoryNode vdn) {
//return visitDeep(vdn);
return ! vdn.hasContentChildren();
}
}
private static class ShowItemVisitor extends DisplayableItemNodeVisitor.Default<Boolean> {
@ -251,13 +255,18 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
}
@Override
public Boolean visit(LocalFileNode dfn) {
return dfn.hasContentChildren();
public Boolean visit(LocalFileNode lfn) {
return lfn.hasContentChildren();
}
@Override
public Boolean visit(LayoutFileNode ln) {
return false;
return ln.hasContentChildren();
}
@Override
public Boolean visit(VirtualDirectoryNode vdn) {
return vdn.hasContentChildren();
}
}
}