From 1f7e98f28e95d9f79a5b40800cff955207c4173d Mon Sep 17 00:00:00 2001 From: raman-bt Date: Fri, 18 Oct 2013 12:22:57 -0400 Subject: [PATCH] Move AddImageTask out of ImageDSProcessor so it can be reused. --- .../autopsy/casemodule/AddImageTask.java | 356 ++++++++++++++++++ .../autopsy/casemodule/ImageDSProcessor.java | 334 ---------------- 2 files changed, 356 insertions(+), 334 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java new file mode 100644 index 0000000000..def759ca5b --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java @@ -0,0 +1,356 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.casemodule; + +import java.awt.EventQueue; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import javax.swing.SwingWorker; +import org.sleuthkit.autopsy.corecomponentinterfaces.DSPCallback; +import org.sleuthkit.autopsy.corecomponentinterfaces.DSPProgressMonitor; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.Image; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.SleuthkitJNI; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskDataException; +import org.sleuthkit.datamodel.TskException; + +public class AddImageTask extends SwingWorker { + + private Logger logger = Logger.getLogger(AddImageTask.class.getName()); + + private Case currentCase; + // true if the process was requested to stop + private boolean cancelled = false; + //true if revert has been invoked. + private boolean reverted = false; + private boolean hasCritError = false; + private boolean addImageDone = false; + + private List errorList = new ArrayList(); + + private DSPProgressMonitor progressMonitor; + private DSPCallback callbackObj; + + private final List newContents = Collections.synchronizedList(new ArrayList()); + + private SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess; + private CurrentDirectoryFetcher fetcher; + + private String imagePath; + private String dataSourcetype; + String timeZone; + boolean noFatOrphans; + + + /* + * Sets the name/path and other options for the iimage to be processed + */ + public void SetImageOptions(String imgPath, String tz, boolean noOrphans) { + this.imagePath = imgPath; + this.timeZone = tz; + this.noFatOrphans = noOrphans; + } + + /* + * A Swingworker that updates the progressMonitor with the name of the + * directory currently being processed by the AddImageTask + */ + private class CurrentDirectoryFetcher extends SwingWorker { + + DSPProgressMonitor progressMonitor; + SleuthkitJNI.CaseDbHandle.AddImageProcess process; + + CurrentDirectoryFetcher(DSPProgressMonitor aProgressMonitor, SleuthkitJNI.CaseDbHandle.AddImageProcess proc) { + this.progressMonitor = aProgressMonitor; + this.process = proc; + } + + /** + * @return the currently processing directory + */ + @Override + protected Integer doInBackground() { + try { + while (!(addImageDone)) { + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + progressMonitor.setText(process.currentDirectory()); + } + }); + + Thread.sleep(2 * 1000); + } + return 1; + } catch (InterruptedException ie) { + return -1; + } + } + } + + + protected AddImageTask(DSPProgressMonitor aProgressMonitor, DSPCallback cbObj ) { + this.progressMonitor = aProgressMonitor; + currentCase = Case.getCurrentCase(); + + this.callbackObj = cbObj; + } + + /** + * Starts the addImage process, but does not commit the results. + * + * @return + * + * @throws Exception + */ + @Override + protected Integer doInBackground() { + + this.setProgress(0); + + errorList.clear(); + try { + //lock DB for writes in EWT thread + //wait until lock acquired in EWT + EventQueue.invokeAndWait(new Runnable() { + @Override + public void run() { + SleuthkitCase.dbWriteLock(); + } + }); + } catch (InterruptedException ex) { + logger.log(Level.WARNING, "Errors occurred while running add image, could not acquire lock. ", ex); + return 0; + + } catch (InvocationTargetException ex) { + logger.log(Level.WARNING, "Errors occurred while running add image, could not acquire lock. ", ex); + return 0; + } + + addImageProcess = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans); + fetcher = new CurrentDirectoryFetcher(progressMonitor, addImageProcess); + + try { + progressMonitor.setIndeterminate(true); + progressMonitor.setProgress(0); + + fetcher.execute(); + addImageProcess.run(new String[]{this.imagePath}); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Core errors occurred while running add image. ", ex); + //critical core/system error and process needs to be interrupted + hasCritError = true; + errorList.add(ex.getMessage()); + } catch (TskDataException ex) { + logger.log(Level.WARNING, "Data errors occurred while running add image. ", ex); + errorList.add(ex.getMessage()); + } finally { + // process is over, doesn't need to be dealt with if cancel happens + + } + + return 0; + } + + /** + * Commit the finished AddImageProcess, and cancel the CleanupTask that + * would have reverted it. + * + * @param settings property set to get AddImageProcess and CleanupTask + * from + * + * @throws Exception if commit or adding the image to the case failed + */ + private void commitImage() throws Exception { + + long imageId = 0; + try { + imageId = addImageProcess.commit(); + } catch (TskException e) { + logger.log(Level.WARNING, "Errors occured while committing the image", e); + errorList.add(e.getMessage()); + } finally { + //commit done, unlock db write in EWT thread + //before doing anything else + SleuthkitCase.dbWriteUnlock(); + + if (imageId != 0) { + Image newImage = Case.getCurrentCase().addImage(imagePath, imageId, timeZone); + + //while we have the image, verify the size of its contents + String verificationErrors = newImage.verifyImageSize(); + if (verificationErrors.equals("") == false) { + //data error (non-critical) + errorList.add(verificationErrors); + } + + // Add the image to the list of new content + newContents.add(newImage); + + } + + logger.log(Level.INFO, "Image committed, imageId: " + imageId); + logger.log(Level.INFO, PlatformUtil.getAllMemUsageInfo()); + } + } + + /** + * + * (called by EventDispatch Thread after doInBackground finishes) + * + * Must Not return without invoking the callBack, unless the caller canceled + */ + @Override + protected void done() { + + setProgress(100); + + // cancel the directory fetcher + fetcher.cancel(true); + + addImageDone = true; + // attempt actions that might fail and force the process to stop + if (cancelled || hasCritError) { + logger.log(Level.INFO, "Handling errors or interruption that occured in add image process"); + revert(); + } + if (!errorList.isEmpty()) { + logger.log(Level.INFO, "Handling non-critical errors that occured in add image process"); + } + + // When everything happens without an error: + if (!(cancelled || hasCritError)) { + + try { + // Tell the progress monitor we're done + progressMonitor.setProgress(100); + + if (newContents.isEmpty()) { + if (addImageProcess != null) { // and if we're done configuring ingest + // commit anything + try { + commitImage(); + } catch (Exception ex) { + errorList.add(ex.getMessage()); + // Log error/display warning + logger.log(Level.SEVERE, "Error adding image to case.", ex); + } + } else { + logger.log(Level.SEVERE, "Missing image process object"); + } + } + + else { //already commited? + logger.log(Level.INFO, "Assuming image already committed, will not commit."); + } + + } catch (Exception ex) { + //handle unchecked exceptions post image add + + errorList.add(ex.getMessage()); + + logger.log(Level.WARNING, "Unexpected errors occurred while running post add image cleanup. ", ex); + + logger.log(Level.SEVERE, "Error adding image to case", ex); + } finally { + + + } + } + + // invoke the callBack, unless the caller cancelled + if (!cancelled) + doCallBack(); + + return; + } + + /* + * Call the callback with proper parameters + */ + private void doCallBack() + { + DSPCallback.DSP_Result result; + + if (hasCritError) { + result = DSPCallback.DSP_Result.CRITICAL_ERRORS; + } + else if (!errorList.isEmpty()) { + result = DSPCallback.DSP_Result.NONCRITICAL_ERRORS; + } + else { + result = DSPCallback.DSP_Result.NO_ERRORS; + } + + // invoke the callcak, passing it the result, list of new contents, and list of errors + callbackObj.done(result, errorList, newContents); + } + + /* + * cancel the image addition, if possible + */ + public void cancelTask() { + + cancelled = true; + + if (!addImageDone) { + try { + interrupt(); + } + catch (Exception ex) { + logger.log(Level.SEVERE, "Failed to interrup the add image task..."); + } + } + else { + try { + revert(); + } + catch(Exception ex) { + logger.log(Level.SEVERE, "Failed to revert the add image task..."); + } + } + } + /* + * Interrurp the add image process if it is still running + */ + private void interrupt() throws Exception { + + try { + logger.log(Level.INFO, "interrupt() add image process"); + addImageProcess.stop(); //it might take time to truly stop processing and writing to db + } catch (TskException ex) { + throw new Exception("Error stopping add-image process.", ex); + } + } + + /* + * Revert - if image has already been added but not committed yet + */ + void revert() { + + if (!reverted) { + + try { + logger.log(Level.INFO, "Revert after add image process"); + try { + addImageProcess.revert(); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Error reverting add image process", ex); + } + } finally { + //unlock db write within EWT thread + SleuthkitCase.dbWriteUnlock(); + } + reverted = true; + } + } + } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java index 89098c8f46..773b31f109 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java @@ -194,339 +194,5 @@ public class ImageDSProcessor implements DataSourceProcessor { } - /* - * Background task that actualy adds the image - */ - private class AddImageTask extends SwingWorker { - - private Logger logger = Logger.getLogger(AddImageTask.class.getName()); - - private Case currentCase; - // true if the process was requested to stop - private boolean cancelled = false; - //true if revert has been invoked. - private boolean reverted = false; - private boolean hasCritError = false; - private boolean addImageDone = false; - - private List errorList = new ArrayList(); - - private DSPProgressMonitor progressMonitor; - private DSPCallback callbackObj; - - private final List newContents = Collections.synchronizedList(new ArrayList()); - - private SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess; - private CurrentDirectoryFetcher fetcher; - - private String imagePath; - private String dataSourcetype; - String timeZone; - boolean noFatOrphans; - - - /* - * Sets the name/path and other options for the iimage to be processed - */ - public void SetImageOptions(String imgPath, String tz, boolean noOrphans) { - this.imagePath = imgPath; - this.timeZone = tz; - this.noFatOrphans = noOrphans; - } - - /* - * A Swingworker that updates the progressMonitor with the name of the - * directory currently being processed by the AddImageTask - */ - private class CurrentDirectoryFetcher extends SwingWorker { - - DSPProgressMonitor progressMonitor; - SleuthkitJNI.CaseDbHandle.AddImageProcess process; - - CurrentDirectoryFetcher(DSPProgressMonitor aProgressMonitor, SleuthkitJNI.CaseDbHandle.AddImageProcess proc) { - this.progressMonitor = aProgressMonitor; - this.process = proc; - } - - /** - * @return the currently processing directory - */ - @Override - protected Integer doInBackground() { - try { - while (!(addImageDone)) { - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - progressMonitor.setText(process.currentDirectory()); - } - }); - - Thread.sleep(2 * 1000); - } - return 1; - } catch (InterruptedException ie) { - return -1; - } - } - } - - - protected AddImageTask(DSPProgressMonitor aProgressMonitor, DSPCallback cbObj ) { - this.progressMonitor = aProgressMonitor; - currentCase = Case.getCurrentCase(); - - this.callbackObj = cbObj; - } - - /** - * Starts the addImage process, but does not commit the results. - * - * @return - * - * @throws Exception - */ - @Override - protected Integer doInBackground() { - - this.setProgress(0); - - errorList.clear(); - try { - //lock DB for writes in EWT thread - //wait until lock acquired in EWT - EventQueue.invokeAndWait(new Runnable() { - @Override - public void run() { - SleuthkitCase.dbWriteLock(); - } - }); - } catch (InterruptedException ex) { - logger.log(Level.WARNING, "Errors occurred while running add image, could not acquire lock. ", ex); - return 0; - - } catch (InvocationTargetException ex) { - logger.log(Level.WARNING, "Errors occurred while running add image, could not acquire lock. ", ex); - return 0; - } - - addImageProcess = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans); - fetcher = new CurrentDirectoryFetcher(progressMonitor, addImageProcess); - - try { - progressMonitor.setIndeterminate(true); - progressMonitor.setProgress(0); - - fetcher.execute(); - addImageProcess.run(new String[]{this.imagePath}); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Core errors occurred while running add image. ", ex); - //critical core/system error and process needs to be interrupted - hasCritError = true; - errorList.add(ex.getMessage()); - } catch (TskDataException ex) { - logger.log(Level.WARNING, "Data errors occurred while running add image. ", ex); - errorList.add(ex.getMessage()); - } finally { - // process is over, doesn't need to be dealt with if cancel happens - - } - - return 0; - } - - /** - * Commit the finished AddImageProcess, and cancel the CleanupTask that - * would have reverted it. - * - * @param settings property set to get AddImageProcess and CleanupTask - * from - * - * @throws Exception if commit or adding the image to the case failed - */ - private void commitImage() throws Exception { - - long imageId = 0; - try { - imageId = addImageProcess.commit(); - } catch (TskException e) { - logger.log(Level.WARNING, "Errors occured while committing the image", e); - errorList.add(e.getMessage()); - } finally { - //commit done, unlock db write in EWT thread - //before doing anything else - SleuthkitCase.dbWriteUnlock(); - - if (imageId != 0) { - Image newImage = Case.getCurrentCase().addImage(imagePath, imageId, timeZone); - - //while we have the image, verify the size of its contents - String verificationErrors = newImage.verifyImageSize(); - if (verificationErrors.equals("") == false) { - //data error (non-critical) - errorList.add(verificationErrors); - } - - // Add the image to the list of new content - newContents.add(newImage); - - } - - logger.log(Level.INFO, "Image committed, imageId: " + imageId); - logger.log(Level.INFO, PlatformUtil.getAllMemUsageInfo()); - } - } - - /** - * - * (called by EventDispatch Thread after doInBackground finishes) - * - * Must Not return without invoking the callBack, unless the caller canceled - */ - @Override - protected void done() { - - setProgress(100); - - // cancel the directory fetcher - fetcher.cancel(true); - - addImageDone = true; - // attempt actions that might fail and force the process to stop - if (cancelled || hasCritError) { - logger.log(Level.INFO, "Handling errors or interruption that occured in add image process"); - revert(); - } - if (!errorList.isEmpty()) { - logger.log(Level.INFO, "Handling non-critical errors that occured in add image process"); - } - - // When everything happens without an error: - if (!(cancelled || hasCritError)) { - - try { - // Tell the progress monitor we're done - progressMonitor.setProgress(100); - - if (newContents.isEmpty()) { - if (addImageProcess != null) { // and if we're done configuring ingest - // commit anything - try { - commitImage(); - } catch (Exception ex) { - errorList.add(ex.getMessage()); - // Log error/display warning - logger.log(Level.SEVERE, "Error adding image to case.", ex); - } - } else { - logger.log(Level.SEVERE, "Missing image process object"); - } - } - - else { //already commited? - logger.log(Level.INFO, "Assuming image already committed, will not commit."); - } - - } catch (Exception ex) { - //handle unchecked exceptions post image add - - errorList.add(ex.getMessage()); - - logger.log(Level.WARNING, "Unexpected errors occurred while running post add image cleanup. ", ex); - - logger.log(Level.SEVERE, "Error adding image to case", ex); - } finally { - - - } - } - - // invoke the callBack, unless the caller cancelled - if (!cancelled) - doCallBack(); - - return; - } - - /* - * Call the callback with proper parameters - */ - private void doCallBack() - { - DSPCallback.DSP_Result result; - - if (hasCritError) { - result = DSPCallback.DSP_Result.CRITICAL_ERRORS; - } - else if (!errorList.isEmpty()) { - result = DSPCallback.DSP_Result.NONCRITICAL_ERRORS; - } - else { - result = DSPCallback.DSP_Result.NO_ERRORS; - } - - // invoke the callcak, passing it the result, list of new contents, and list of errors - callbackObj.done(result, errorList, newContents); - } - - /* - * cancel the image addition, if possible - */ - public void cancelTask() { - - cancelled = true; - - if (!addImageDone) { - try { - addImageTask.interrupt(); - } - catch (Exception ex) { - logger.log(Level.SEVERE, "Failed to interrup the add image task..."); - } - } - else { - try { - addImageTask.revert(); - } - catch(Exception ex) { - logger.log(Level.SEVERE, "Failed to revert the add image task..."); - } - } - } - /* - * Interrurp the add image process if it is still running - */ - private void interrupt() throws Exception { - - try { - logger.log(Level.INFO, "interrupt() add image process"); - addImageProcess.stop(); //it might take time to truly stop processing and writing to db - } catch (TskException ex) { - throw new Exception("Error stopping add-image process.", ex); - } - } - - /* - * Revert - if image has already been added but not committed yet - */ - void revert() { - - if (!reverted) { - - try { - logger.log(Level.INFO, "Revert after add image process"); - try { - addImageProcess.revert(); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Error reverting add image process", ex); - } - } finally { - //unlock db write within EWT thread - SleuthkitCase.dbWriteUnlock(); - } - reverted = true; - } - } - } }