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