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.concurrent.ExecutorService;
34 import java.util.logging.Level;
35 import org.netbeans.api.progress.ProgressHandle;
36 import org.openide.util.NbBundle.Messages;
56 class ImageWriter
implements PropertyChangeListener {
60 private final Long dataSourceId;
63 private Long imageHandle = null;
64 private Future<Integer> finishTask = null;
65 private ProgressHandle progressHandle = null;
66 private ScheduledFuture<?> progressUpdateTask = null;
67 private boolean isCancelled =
false;
68 private boolean isStarted =
false;
69 private final Object currentTasksLock =
new Object();
72 private ScheduledThreadPoolExecutor periodicTasksExecutor = null;
73 private final boolean doUI;
83 this.dataSourceId = dataSourceId;
84 this.settings = settings;
93 logger.log(Level.SEVERE,
"Unable to load case. Image writer will be cancelled.");
94 this.isCancelled =
true;
101 void subscribeToEvents() {
109 void unsubscribeFromEvents() {
118 public void propertyChange(PropertyChangeEvent evt) {
121 DataSourceAnalysisCompletedEvent
event = (DataSourceAnalysisCompletedEvent) evt;
123 if (event.getDataSource() != null) {
124 long imageId =
event.getDataSource().getId();
125 String name =
event.getDataSource().getName();
128 if (imageId != dataSourceId) {
132 startFinishImage(name);
136 logger.log(Level.SEVERE,
"DataSourceAnalysisCompletedEvent did not contain a dataSource object");
142 "# {0} - data source name",
143 "ImageWriter.progressBar.message=Finishing acquisition of {0} (unplug device to cancel)"
145 private void startFinishImage(String dataSourceName) {
147 ExecutorService executor = Executors.newSingleThreadExecutor(
new ThreadFactoryBuilder().setNameFormat(
"ImageWriter-startFinishImage-%d").build());
148 synchronized (currentTasksLock) {
169 logger.log(Level.WARNING, String.format(
"Case closed before ImageWriter could start the finishing process for %s",
173 logger.log(Level.SEVERE,
"Error loading image", ex);
177 logger.log(Level.INFO, String.format(
"Finishing VHD image for %s",
181 periodicTasksExecutor =
new ScheduledThreadPoolExecutor(1,
new ThreadFactoryBuilder().setNameFormat(
"image-writer-progress-update-%d").build());
182 progressHandle = ProgressHandle.createHandle(Bundle.ImageWriter_progressBar_message(dataSourceName));
183 progressHandle.start(100);
184 progressUpdateTask = periodicTasksExecutor.scheduleWithFixedDelay(
185 new ProgressUpdateTask(progressHandle, imageHandle), 0, 250, TimeUnit.MILLISECONDS);
191 finishTask = executor.submit(
new Callable<Integer>() {
204 }
catch (Throwable ex) {
205 logger.log(Level.SEVERE,
"Error finishing VHD image", ex);
219 result = finishTask.get();
220 executor.shutdownNow();
221 }
catch (InterruptedException | ExecutionException ex) {
222 logger.log(Level.SEVERE,
"Error finishing VHD image", ex);
225 synchronized (currentTasksLock) {
228 progressUpdateTask.cancel(
true);
229 progressHandle.finish();
230 periodicTasksExecutor.shutdown();
235 logger.log(Level.INFO, String.format(
"Successfully finished writing VHD image for %s", dataSourceName));
237 logger.log(Level.INFO, String.format(
"Finished VHD image for %s with errors", dataSourceName));
246 void cancelIfNotStarted() {
247 synchronized (currentTasksLock) {
260 boolean jobIsInProgress() {
261 synchronized (currentTasksLock) {
262 return ((isStarted) && (!finishTask.isDone()));
271 synchronized (currentTasksLock) {
285 progressUpdateTask.cancel(
true);
286 progressHandle.finish();
296 void waitForJobToFinish() {
297 synchronized (currentTasksLock) {
302 }
catch (InterruptedException | ExecutionException ex) {
303 Logger.
getLogger(ImageWriter.class.getName()).log(Level.SEVERE,
"Error finishing VHD image", ex);
306 progressUpdateTask.cancel(
true);
317 final long imageHandle;
318 final ProgressHandle progressHandle;
321 this.imageHandle = imageHandle;
322 this.progressHandle = progressHandle;
329 progressHandle.progress(progress);
330 }
catch (Exception ex) {
331 logger.log(Level.SEVERE,
"Unexpected exception in ProgressUpdateTask", ex);
static synchronized IngestManager getInstance()
static void cancelFinishImage(long imgHandle)
static boolean runningWithGUI
static int finishImageWriter(long imgHandle)
DATA_SOURCE_ANALYSIS_COMPLETED
void removeIngestJobEventListener(final PropertyChangeListener listener)
Image getImageById(long id)
void addIngestJobEventListener(final PropertyChangeListener listener)
SleuthkitCase getSleuthkitCase()
static int getFinishImageProgress(long imgHandle)
void updateImagePath(String newPath, long objectId)
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
boolean getUpdateDatabasePath()
synchronized long getImageHandle()