diff --git a/DataModel/nbproject/project.xml b/DataModel/nbproject/project.xml
index f0b7259357..c57866e184 100644
--- a/DataModel/nbproject/project.xml
+++ b/DataModel/nbproject/project.xml
@@ -6,6 +6,15 @@
org.sleuthkit.autopsy.datamodel
+
+ org.netbeans.api.progress
+
+
+
+ 1
+ 1.28.1
+
+
org.openide.awt
diff --git a/DataModel/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java b/DataModel/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java
index 565e2348c6..2fb43af3fb 100644
--- a/DataModel/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java
+++ b/DataModel/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java
@@ -28,6 +28,8 @@ import java.util.List;
import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.swing.SwingWorker;
+import org.netbeans.api.progress.ProgressHandle;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentVisitor;
import org.sleuthkit.datamodel.Directory;
@@ -214,25 +216,47 @@ public final class ContentUtils {
* it does
* @throws IOException
*/
- public static void writeToFile(Content content, java.io.File outputFile) throws IOException {
+ public static void writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, SwingWorker worker, boolean source) throws IOException {
InputStream in = new ReadContentInputStream(content);
boolean append = false;
FileOutputStream out = new FileOutputStream(outputFile, append);
+
+ // Get the unit size for a progress bar
+ int unit = (int) (content.getSize() / 100);
+ long totalRead = 0;
try {
byte[] buffer = new byte[TO_FILE_BUFFER_SIZE];
int len = in.read(buffer);
while (len != -1) {
+ // If there is a worker, check for a cancelation
+ if (worker!=null && worker.isCancelled()) {
+ break;
+ }
out.write(buffer, 0, len);
len = in.read(buffer);
+ totalRead+=len;
+ // If there is a progress bar and this is the source file,
+ // report any progress
+ if(progress!=null && source) {
+ int totalProgress = (int) (totalRead / unit);
+ progress.progress(content.getName(), totalProgress);
+ // If it's not the source, just update the file being processed
+ } else if(progress!=null && !source) {
+ progress.progress(content.getName());
+ }
}
} finally {
out.close();
}
}
+ public static void writeToFile(Content content, java.io.File outputFile) throws IOException {
+ writeToFile(content, outputFile, null, null, false);
+ }
+
/**
* Helper to ignore the '.' and '..' directories
*/
@@ -250,11 +274,21 @@ public final class ContentUtils {
public static class ExtractFscContentVisitor extends ContentVisitor.Default {
java.io.File dest;
+ ProgressHandle progress;
+ SwingWorker worker;
+ boolean source = false;
/**
* Make new extractor for a specific destination
* @param dest The file/folder visited will be extracted as this file
*/
+ public ExtractFscContentVisitor(java.io.File dest, ProgressHandle progress, SwingWorker worker, boolean source) {
+ this.dest = dest;
+ this.progress = progress;
+ this.worker = worker;
+ this.source = source;
+ }
+
public ExtractFscContentVisitor(java.io.File dest) {
this.dest = dest;
}
@@ -263,13 +297,13 @@ public final class ContentUtils {
* Convenience method to make a new instance for given destination
* and extract given content
*/
- public static void extract(Content cntnt, java.io.File dest) {
- cntnt.accept(new ExtractFscContentVisitor(dest));
+ public static void extract(Content cntnt, java.io.File dest, ProgressHandle progress, SwingWorker worker) {
+ cntnt.accept(new ExtractFscContentVisitor(dest, progress, worker, true));
}
public Void visit(File f) {
try {
- ContentUtils.writeToFile(f, dest);
+ ContentUtils.writeToFile(f, dest, progress, worker, source);
} catch (IOException ex) {
logger.log(Level.SEVERE,
"Trouble extracting file to " + dest.getAbsolutePath(),
@@ -292,12 +326,23 @@ public final class ContentUtils {
DestFileContentVisitor destFileCV = new DestFileContentVisitor();
try {
+ int numProcessed = 0;
// recurse on children
for (Content child : dir.getChildren()) {
java.io.File childFile = child.accept(destFileCV);
ExtractFscContentVisitor childVisitor =
- new ExtractFscContentVisitor(childFile);
+ new ExtractFscContentVisitor(childFile, progress, worker, false);
+ // If this is the source directory of an extract it
+ // will have a progress and worker, and will keep track
+ // of the progress bar's progress
+ if(worker!=null && worker.isCancelled()) {
+ break;
+ }
+ if(progress!=null && source) {
+ progress.progress(child.getName(), numProcessed);
+ }
child.accept(childVisitor);
+ numProcessed++;
}
} catch (TskException ex) {
logger.log(Level.SEVERE,
diff --git a/DirectoryTree/nbproject/project.xml b/DirectoryTree/nbproject/project.xml
index e4b2710e0f..a0eea2fa8b 100644
--- a/DirectoryTree/nbproject/project.xml
+++ b/DirectoryTree/nbproject/project.xml
@@ -6,6 +6,15 @@
org.sleuthkit.autopsy.directorytree
+
+ org.netbeans.api.progress
+
+
+
+ 1
+ 1.28.1
+
+
org.netbeans.modules.settings
diff --git a/DirectoryTree/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java b/DirectoryTree/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java
index 672720cd13..7b288fbe85 100644
--- a/DirectoryTree/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java
+++ b/DirectoryTree/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java
@@ -18,17 +18,23 @@
*/
package org.sleuthkit.autopsy.directorytree;
-import java.awt.event.ActionEvent;
-import javax.swing.JFileChooser;
-import java.io.File;
import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.io.File;
+import java.util.concurrent.CancellationException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import javax.swing.AbstractAction;
+import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
+import javax.swing.SwingWorker;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.api.progress.ProgressHandleFactory;
import org.openide.nodes.Node;
+import org.openide.util.Cancellable;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor;
-import org.sleuthkit.autopsy.coreutils.Log;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentVisitor;
import org.sleuthkit.datamodel.Directory;
@@ -41,6 +47,7 @@ public final class ExtractAction extends AbstractAction {
private static final InitializeContentVisitor initializeCV = new InitializeContentVisitor();
private FsContent fsContent;
+ private Logger logger = Logger.getLogger(ExtractAction.class.getName());
public ExtractAction(String title, Node contentNode) {
super(title);
@@ -78,8 +85,7 @@ public final class ExtractAction extends AbstractAction {
*/
@Override
public void actionPerformed(ActionEvent e) {
- Log.noteAction(this.getClass());
-
+ // Get file and check that it's okay to overwrite existing file
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(new File(Case.getCurrentCase().getCaseDirectory()));
fc.setSelectedFile(new File(this.fsContent.getName()));
@@ -88,7 +94,7 @@ public final class ExtractAction extends AbstractAction {
if (returnValue == JFileChooser.APPROVE_OPTION) {
File destination = fc.getSelectedFile();
- // check that it's okay to overwrite existing file
+ // do the check
if (destination.exists()) {
int choice = JOptionPane.showConfirmDialog(
(Component) e.getSource(),
@@ -97,7 +103,7 @@ public final class ExtractAction extends AbstractAction {
JOptionPane.OK_CANCEL_OPTION);
if (choice != JOptionPane.OK_OPTION) {
- return;
+ return; // Just exit the function
}
if (!destination.delete()) {
@@ -106,13 +112,134 @@ public final class ExtractAction extends AbstractAction {
"Couldn't delete existing file.");
}
}
-
- ExtractFscContentVisitor.extract(fsContent, destination);
- if(fsContent.isDir())
- JOptionPane.showMessageDialog((Component) e.getSource(), "Directory extracted.");
- else if(fsContent.isFile()){
- JOptionPane.showMessageDialog((Component) e.getSource(), "File extracted.");
+
+ try {
+ ExtractFileThread extract = new ExtractFileThread();
+ extract.init(this.fsContent, e, destination);
+ extract.execute();
+ } catch (Exception ex) {
+ logger.log(Level.WARNING, "Unable to start background thread.", ex);
}
}
}
+
+ private class ExtractFileThread extends SwingWorker