19 package org.sleuthkit.autopsy.imagewriter;
21 import com.google.common.util.concurrent.ThreadFactoryBuilder;
22 import java.beans.PropertyChangeEvent;
23 import java.beans.PropertyChangeListener;
24 import java.util.EnumSet;
26 import java.util.concurrent.Callable;
27 import java.util.concurrent.Executors;
28 import java.util.concurrent.Future;
29 import java.util.concurrent.ScheduledFuture;
30 import java.util.concurrent.ScheduledThreadPoolExecutor;
31 import java.util.concurrent.TimeUnit;
32 import java.util.concurrent.ExecutionException;
33 import java.util.logging.Level;
34 import org.netbeans.api.progress.ProgressHandle;
35 import org.openide.util.NbBundle.Messages;
55 class ImageWriter
implements PropertyChangeListener {
59 private final Long dataSourceId;
62 private Long imageHandle = null;
63 private Future<Integer> finishTask = null;
64 private ProgressHandle progressHandle = null;
65 private ScheduledFuture<?> progressUpdateTask = null;
66 private boolean isCancelled =
false;
67 private boolean isStarted =
false;
68 private final Object currentTasksLock =
new Object();
71 private ScheduledThreadPoolExecutor periodicTasksExecutor = null;
72 private final boolean doUI;
73 private SleuthkitCase caseDb = null;
82 this.dataSourceId = dataSourceId;
83 this.settings = settings;
92 logger.log(Level.SEVERE,
"Unable to load case. Image writer will be cancelled.");
93 this.isCancelled =
true;
100 void subscribeToEvents() {
108 void unsubscribeFromEvents() {
117 public void propertyChange(PropertyChangeEvent evt) {
120 DataSourceAnalysisCompletedEvent
event = (DataSourceAnalysisCompletedEvent) evt;
122 if (event.getDataSource() != null) {
123 long imageId =
event.getDataSource().getId();
124 String name =
event.getDataSource().getName();
127 if (imageId != dataSourceId) {
131 startFinishImage(name);
135 logger.log(Level.SEVERE,
"DataSourceAnalysisCompletedEvent did not contain a dataSource object");
141 "# {0} - data source name",
142 "ImageWriter.progressBar.message=Finishing acquisition of {0} (unplug device to cancel)"
144 private void startFinishImage(String dataSourceName) {
146 synchronized (currentTasksLock) {
161 imageHandle = image.getImageHandle();
167 logger.log(Level.WARNING, String.format(
"Case closed before ImageWriter could start the finishing process for %s",
170 }
catch (TskCoreException ex) {
171 logger.log(Level.SEVERE,
"Error loading image", ex);
175 logger.log(Level.INFO, String.format(
"Finishing VHD image for %s",
179 periodicTasksExecutor =
new ScheduledThreadPoolExecutor(1,
new ThreadFactoryBuilder().setNameFormat(
"image-writer-progress-update-%d").build());
180 progressHandle = ProgressHandle.createHandle(Bundle.ImageWriter_progressBar_message(dataSourceName));
181 progressHandle.start(100);
182 progressUpdateTask = periodicTasksExecutor.scheduleWithFixedDelay(
183 new ProgressUpdateTask(progressHandle, imageHandle), 0, 250, TimeUnit.MILLISECONDS);
189 finishTask = Executors.newSingleThreadExecutor().submit(
new Callable<Integer>() {
191 public Integer call()
throws TskCoreException {
193 int result = SleuthkitJNI.finishImageWriter(imageHandle);
199 caseDb.updateImagePath(settings.
getPath(), dataSourceId);
202 }
catch (TskCoreException ex) {
203 logger.log(Level.SEVERE,
"Error finishing VHD image", ex);
217 result = finishTask.get();
218 }
catch (InterruptedException | ExecutionException ex) {
219 logger.log(Level.SEVERE,
"Error finishing VHD image", ex);
222 synchronized (currentTasksLock) {
225 progressUpdateTask.cancel(
true);
226 progressHandle.finish();
227 periodicTasksExecutor.shutdown();
232 logger.log(Level.INFO, String.format(
"Successfully finished writing VHD image for %s", dataSourceName));
234 logger.log(Level.INFO, String.format(
"Finished VHD image for %s with errors", dataSourceName));
243 void cancelIfNotStarted() {
244 synchronized (currentTasksLock) {
257 boolean jobIsInProgress() {
258 synchronized (currentTasksLock) {
259 return ((isStarted) && (!finishTask.isDone()));
268 synchronized (currentTasksLock) {
273 SleuthkitJNI.cancelFinishImage(imageHandle);
282 progressUpdateTask.cancel(
true);
283 progressHandle.finish();
293 void waitForJobToFinish() {
294 synchronized (currentTasksLock) {
299 }
catch (InterruptedException | ExecutionException ex) {
300 Logger.
getLogger(ImageWriter.class.getName()).log(Level.SEVERE,
"Error finishing VHD image", ex);
303 progressUpdateTask.cancel(
true);
314 final long imageHandle;
315 final ProgressHandle progressHandle;
318 this.imageHandle = imageHandle;
319 this.progressHandle = progressHandle;
325 int progress = SleuthkitJNI.getFinishImageProgress(imageHandle);
326 progressHandle.progress(progress);
327 }
catch (Exception ex) {
328 logger.log(Level.SEVERE,
"Unexpected exception in ProgressUpdateTask", ex);
static synchronized IngestManager getInstance()
static boolean runningWithGUI
DATA_SOURCE_ANALYSIS_COMPLETED
void removeIngestJobEventListener(final PropertyChangeListener listener)
void addIngestJobEventListener(final PropertyChangeListener listener)
SleuthkitCase getSleuthkitCase()
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
boolean getUpdateDatabasePath()