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()