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.concurrent.Callable;
 
   25 import java.util.concurrent.Executors;
 
   26 import java.util.concurrent.Future;
 
   27 import java.util.concurrent.ScheduledFuture;
 
   28 import java.util.concurrent.ScheduledThreadPoolExecutor;
 
   29 import java.util.concurrent.TimeUnit;
 
   30 import java.util.concurrent.ExecutionException;
 
   31 import java.util.logging.Level;
 
   32 import org.netbeans.api.progress.ProgressHandle;
 
   50 class ImageWriter 
implements PropertyChangeListener{
 
   54     private final Long dataSourceId;
 
   57     private Long imageHandle = null;
 
   58     private Future<Integer> finishTask = null;
 
   59     private ProgressHandle progressHandle = null;
 
   60     private ScheduledFuture<?> progressUpdateTask = null;
 
   61     private boolean isCancelled = 
false;
 
   62     private boolean isStarted = 
false;
 
   63     private final Object currentTasksLock = 
new Object(); 
 
   66     private ScheduledThreadPoolExecutor periodicTasksExecutor = null;
 
   67     private final boolean doUI;
 
   76         this.dataSourceId = dataSourceId;     
 
   77         this.settings = settings;
 
   85         } 
catch (IllegalStateException ex){
 
   86             logger.log(Level.SEVERE, 
"Unable to load case. Image writer will be cancelled.");
 
   87             this.isCancelled = 
true;
 
   94     void subscribeToEvents(){
 
  101     void unsubscribeFromEvents(){
 
  110     public void propertyChange(PropertyChangeEvent evt) {
 
  113             DataSourceAnalysisCompletedEvent 
event = (DataSourceAnalysisCompletedEvent)evt;
 
  115             if(event.getDataSource() != null){
 
  116                 long imageId = 
event.getDataSource().getId();
 
  117                 String name = 
event.getDataSource().getName();
 
  120                 if(imageId != dataSourceId){
 
  124                     startFinishImage(name);
 
  128                 logger.log(Level.SEVERE, 
"DataSourceAnalysisCompletedEvent did not contain a dataSource object"); 
 
  133     private void startFinishImage(String dataSourceName){
 
  135         synchronized(currentTasksLock){
 
  151             } 
catch (IllegalStateException ex){
 
  156                 logger.log(Level.WARNING, String.format(
"Case closed before ImageWriter could start the finishing process for %s",
 
  160                 logger.log(Level.SEVERE, 
"Error loading image", ex);
 
  164             logger.log(Level.INFO, String.format(
"Finishing VHD image for %s", 
 
  168                 periodicTasksExecutor = 
new ScheduledThreadPoolExecutor(1, 
new ThreadFactoryBuilder().setNameFormat(
"image-writer-progress-update-%d").build()); 
 
  169                 progressHandle = ProgressHandle.createHandle(
"Image writer - " + dataSourceName);
 
  170                 progressHandle.start(100);
 
  171                 progressUpdateTask = periodicTasksExecutor.scheduleAtFixedRate(
 
  172                         new ProgressUpdateTask(progressHandle, imageHandle), 0, 250, TimeUnit.MILLISECONDS);
 
  178             finishTask = Executors.newSingleThreadExecutor().submit(
new Callable<Integer>(){
 
  192                         logger.log(Level.SEVERE, 
"Error finishing VHD image", ex); 
 
  206             result = finishTask.get();
 
  207         } 
catch (InterruptedException | ExecutionException ex){
 
  208             logger.log(Level.SEVERE, 
"Error finishing VHD image", ex); 
 
  211         synchronized(currentTasksLock){
 
  214                 progressUpdateTask.cancel(
true);
 
  215                 progressHandle.finish();
 
  216                 periodicTasksExecutor.shutdown();
 
  221             logger.log(Level.INFO, String.format(
"Successfully finished writing VHD image for %s", dataSourceName)); 
 
  223             logger.log(Level.INFO, String.format(
"Finished VHD image for %s with errors", dataSourceName)); 
 
  233     void cancelIfNotStarted(){
 
  234         synchronized(currentTasksLock){
 
  246     boolean jobIsInProgress(){
 
  247         synchronized(currentTasksLock){
 
  248             return((isStarted) && (! finishTask.isDone()));
 
  257         synchronized(currentTasksLock){
 
  271                     progressUpdateTask.cancel(
true);
 
  272                     progressHandle.finish();
 
  282     void waitForJobToFinish(){
 
  283         synchronized(currentTasksLock){
 
  288                 } 
catch (InterruptedException | ExecutionException ex){
 
  289                     Logger.
getLogger(ImageWriter.class.getName()).log(Level.SEVERE, 
"Error finishing VHD image", ex); 
 
  292                     progressUpdateTask.cancel(
true);
 
  302         final long imageHandle;
 
  303         final ProgressHandle progressHandle;
 
  306             this.imageHandle = imageHandle;
 
  307             this.progressHandle = progressHandle;
 
  314                 progressHandle.progress(progress);
 
  315             } 
catch (Exception ex) {
 
  316                 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)
 
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)
 
static Case getCurrentCase()
 
synchronized static Logger getLogger(String name)
 
boolean getUpdateDatabasePath()
 
synchronized long getImageHandle()