From 7b52520f9022141a2af55c6ba9f404c44b15764d Mon Sep 17 00:00:00 2001 From: raman-bt Date: Fri, 11 Oct 2013 12:16:07 -0400 Subject: [PATCH 01/21] Cleanup of Add Image/DataSource Wizard. Pass #1. --- .../AddImageWizardChooseDataSourcePanel.java | 7 + .../AddImageWizardChooseDataSourceVisual.java | 81 ++- .../AddImageWizardIngestConfigPanel.java | 96 ++- .../casemodule/AddImageWizardIterator.java | 13 +- .../autopsy/casemodule/ContentTypePanel.java | 28 +- .../autopsy/casemodule/DSPCallback.java | 42 ++ .../casemodule/DataSourceProcessor.java | 87 +++ .../autopsy/casemodule/ImageDSProcessor.java | 566 ++++++++++++++++++ .../autopsy/casemodule/ImageFilePanel.java | 4 +- .../autopsy/casemodule/LocalDiskPanel.java | 4 +- .../autopsy/casemodule/LocalFilesPanel.java | 4 +- 11 files changed, 905 insertions(+), 27 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/DSPCallback.java create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/DataSourceProcessor.java create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java index 39a00baacc..7fb2a69b0b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java @@ -43,6 +43,7 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel datasourceProcessorsMap = new HashMap();; + + /** * Creates new form AddImageVisualPanel1 @@ -75,13 +87,55 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { } private void customInit() { + + + discoverDataSourceProcessors(); + model = new ContentTypeModel(); typeComboBox.setModel(model); typeComboBox.setSelectedIndex(0); typePanel.setLayout(new BorderLayout()); - updateCurrentPanel(ImageFilePanel.getDefault()); + + //updateCurrentPanel(ImageFilePanel.getDefault()); + updateCurrentPanel(model.getElementAt(0)); } + private void discoverDataSourceProcessors() { + + //datasourceHandlersMap.clear(); + logger.log(Level.INFO, "RAMAN discoverDataSourceProcessors()..."); + + // RAMAN TBD: hack for now + { + //ContentTypePanel.RegisterPanel(ImageFilePanel.getDefault()); + //ContentTypePanel.RegisterPanel(LocalDiskPanel.getDefault()); + //ContentTypePanel.RegisterPanel(LocalFilesPanel.getDefault()); + } + + for (DataSourceProcessor dsProcessor: Lookup.getDefault().lookupAll(DataSourceProcessor.class)) { + + logger.log(Level.INFO, "RAMAN discoverDataSourceHandlers(): found an instance of DataSourceHandler"); + + + String dsType = dsProcessor.getType(); + JPanel panel = dsProcessor.getPanel(); + String validate = dsProcessor.validatePanel(); + //dshandler.run(null); + //String[] errors = dshandler.getErrors(); + + if (!datasourceProcessorsMap.containsKey(dsProcessor.getType()) ) { + + // Regsiter the panel for the discovered DS handler here + ContentTypePanel.RegisterPanel(dsProcessor.getPanel()); + + datasourceProcessorsMap.put(dsProcessor.getType(), dsProcessor); + } + + } + + + } + /** * Changes the current panel to the given panel. * @@ -105,7 +159,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { } }); currentPanel.select(); - if (currentPanel.getContentType().equals(ContentType.LOCAL)) { + if (currentPanel.getContentType().equals("LOCAL")) { //disable image specific options noFatOrphansCheckbox.setEnabled(false); descLabel.setEnabled(false); @@ -118,6 +172,25 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { updateUI(null); } + /** + * Returns the currently selected DS handler in the combobox + * + * + * @return name the name of this panel + */ + public DataSourceProcessor GetCurrentDSProcessor() { + + logger.log(Level.INFO, "RAMAN GetCurrentDSProcessor()..."); + // get the type of the currently selected panel and then look up + // the correspodning DS Handler in the map + String dsType = currentPanel.getContentType(); + + DataSourceProcessor dsProcessor = datasourceProcessorsMap.get(dsType); + + return dsProcessor; + + } + /** * Returns the name of the this panel. This name will be shown on the left * panel of the "Add Image" wizard panel. @@ -143,7 +216,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { * * @return data source selected */ - public ContentType getContentType() { + public String getContentType() { return currentPanel.getContentType(); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java index 3f5b77e281..dab6bf7318 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java @@ -37,7 +37,7 @@ import javax.swing.event.ChangeListener; import org.openide.WizardDescriptor; import org.openide.util.HelpCtx; import org.openide.util.Lookup; -import org.sleuthkit.autopsy.casemodule.ContentTypePanel.ContentType; +//import org.sleuthkit.autopsy.casemodule.ContentTypePanel.ContentType; import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.PlatformUtil; @@ -73,7 +73,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel messages = ingestConfig.setContext(AddImageWizardIngestConfigPanel.class.getCanonicalName()); if (messages.isEmpty() == false) { @@ -188,12 +193,13 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel errList, List contents) { + dataSourceProcessorDone(result, errList, contents ); + } + + }; + // Kick off the DSProcessor + dsProcessor.run(settings, progressPanel, cbObj); + } + private void cancelDataSourceProcessing() { + logger.log(Level.INFO, "RAMAN cancelDataSourceProcessing()."); + dsProcessor.cancel(); + } + + private void dataSourceProcessorDone(DSPCallback.DSP_Result result, List errList, List contents) { + logger.log(Level.INFO, "RAMAN dataSourceProcessorDone()."); + + // RAMAN TBD + // check if there is any new content and kick off ingest.... + + // RAMAN TBD: check the result + + // RAMAN TBD: if errors, display them on the progress panel + + // disbale the cleanup task + cleanupTask.disable(); + + + newContents.clear(); + newContents.addAll(contents); + + //notify the case + if (!newContents.isEmpty()) { + Case.getCurrentCase().addLocalDataSource(newContents.get(0)); + } + + // Start ingest if we can + startIngest(); + + } /** * Class for getting the currently processing directory. * @@ -313,7 +389,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel> getPanels() { if (panels == null) { - AddImageWizardAddingProgressPanel wizPanel = new AddImageWizardAddingProgressPanel(); panels = new ArrayList>(); - panels.add(new AddImageWizardChooseDataSourcePanel()); - panels.add(new AddImageWizardIngestConfigPanel(action, wizPanel)); - panels.add(wizPanel); + + AddImageWizardAddingProgressPanel progressPanel = new AddImageWizardAddingProgressPanel(); + + AddImageWizardChooseDataSourcePanel dsPanel = new AddImageWizardChooseDataSourcePanel(progressPanel); + AddImageWizardIngestConfigPanel ingestConfigPanel = new AddImageWizardIngestConfigPanel(dsPanel, action, progressPanel); + + panels.add(dsPanel); + panels.add(ingestConfigPanel); + panels.add(progressPanel); String[] steps = new String[panels.size()]; for (int i = 0; i < panels.size(); i++) { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ContentTypePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ContentTypePanel.java index 07664d9401..4b2f4aada8 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ContentTypePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ContentTypePanel.java @@ -20,17 +20,39 @@ package org.sleuthkit.autopsy.casemodule; import java.beans.PropertyChangeListener; import javax.swing.JPanel; +import java.util.ArrayList; +import java.util.List; abstract class ContentTypePanel extends JPanel { - public enum ContentType{IMAGE, DISK, LOCAL}; + // Collection of panels that are dynamically discovered and registered + private static List registeredPanels = new ArrayList();; + + public static void RegisterPanel(ContentTypePanel panel) + { + // RAMAN TBD: check if this panel is already regsitered... + + registeredPanels.add(panel); + + + } + //public enum ContentType{IMAGE, DISK, LOCAL}; + + + private String contentType; /** * Returns a list off all the panels extending ImageTypePanel. * @return list of all ImageTypePanels */ public static ContentTypePanel[] getPanels() { - return new ContentTypePanel[] {ImageFilePanel.getDefault(), LocalDiskPanel.getDefault(), LocalFilesPanel.getDefault() }; + //return new ContentTypePanel[] {ImageFilePanel.getDefault(), LocalDiskPanel.getDefault(), LocalFilesPanel.getDefault() }; + + + + + + return registeredPanels.toArray(new ContentTypePanel[registeredPanels.size()]); } /** @@ -50,7 +72,7 @@ abstract class ContentTypePanel extends JPanel { * Get content type (image, disk, local file) of the source this wizard panel is for * @return ContentType of the source panel */ - abstract public ContentType getContentType(); + abstract public String getContentType(); /** * Returns if the next button should be enabled in the current wizard. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/DSPCallback.java b/Core/src/org/sleuthkit/autopsy/casemodule/DSPCallback.java new file mode 100644 index 0000000000..58ec4d8ce0 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/DSPCallback.java @@ -0,0 +1,42 @@ +/* + * 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.util.List; +import org.sleuthkit.datamodel.Content; + +/** + * + * @author raman + */ +public abstract class DSPCallback { + + public enum DSP_Result + { + NO_ERRORS, + CRITICAL_ERRORS, + NONCRITICAL_ERRORS, + }; + + void done(DSP_Result result, List errList, List newContents) + { + + final DSP_Result resultf = result; + final List errListf = errList; + final List newContentsf = newContents; + + // Invoke doneEDT() that runs on the EDT . + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + doneEDT(resultf, errListf, newContentsf ); + + } + }); + } + + abstract void doneEDT(DSP_Result result, List errList, List newContents); +}; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/DataSourceProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/DataSourceProcessor.java new file mode 100644 index 0000000000..123d26275b --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/DataSourceProcessor.java @@ -0,0 +1,87 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2013 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.casemodule; + +import java.util.List; +import javax.swing.JPanel; +import org.openide.WizardDescriptor; +import org.sleuthkit.autopsy.casemodule.AddImageWizardAddingProgressPanel; +import org.sleuthkit.autopsy.casemodule.ContentTypePanel; +import org.sleuthkit.datamodel.Content; + +public interface DataSourceProcessor { + + + + + // public DataSourceProcessor createInstance(); + + + /** + * Returns the type of Data Source it handles. + * This name gets displayed in the drop-down listbox + **/ + String getType(); + + /** + * Returns the picker panel to be displayed along with any other + * runtime options supported by the data source handler. + **/ + ContentTypePanel getPanel(); + + /** + * Called to validate the input data in the panel. + * Returns null if no errors, or + * Returns a string describing the error if there are errors. + **/ + String validatePanel(); + + /** + * Called to invoke the handling of Data source in the background. + * Returns after starting the background thread + * @param settings wizard settings to read/store properties + * @param progressPanel progress panel to be updated while processing + * + **/ + void run(WizardDescriptor settings, AddImageWizardAddingProgressPanel progressPanel, DSPCallback dspCallback); + + /** + * Called after run() is done to get the new content added by the handler. + * Returns a list of content added by the data source handler + **/ + // List getNewContents(); + + + /** + * Called to get the list of errors. + **/ + // String[] getErrors(); + + /** + * Called to cancel the background processing. + * + * TODO look into current use cases to see if this should wait until it has stopped or not. + **/ + void cancel(); + + + + + +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java new file mode 100644 index 0000000000..e44c0f32a1 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java @@ -0,0 +1,566 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.casemodule; + +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Window; +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.JPanel; +import javax.swing.JProgressBar; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; +import org.openide.WizardDescriptor; +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; +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; + +/** + * + * @author raman + */ +@ServiceProvider(service = DataSourceProcessor.class) +public class ImageDSProcessor implements DataSourceProcessor { + + static final Logger logger = Logger.getLogger(ImageDSProcessor.class.getName()); + + private ImageFilePanel imageFilePanel; + private AddImageTask addImageTask; + private CurrentDirectoryFetcher fetcher; + + private boolean addImageDone = false; + private boolean cancelled = false; + + DSPCallback callbackObj = null; + + public ImageDSProcessor() { + logger.log(Level.INFO, "RAMAN ImageDSHandler()..."); + + // Create the config panel + imageFilePanel = ImageFilePanel.getDefault(); + + } + + /**** + @Override + public ImageDSProcessor createInstance() { + return new ImageDSProcessor(); + } + *****/ + + + @Override + public String getType() { + + logger.log(Level.INFO, "RAMAN getName()..."); + + return imageFilePanel.getContentType(); + + } + + + @Override + public ContentTypePanel getPanel() { + + logger.log(Level.INFO, "RAMAN getPanel()..."); + + return imageFilePanel; + } + + @Override + public String validatePanel() { + + logger.log(Level.INFO, "RAMAN validatePanel()..."); + + return null; + + } + + @Override + public void run(WizardDescriptor settings, AddImageWizardAddingProgressPanel progressPanel, DSPCallback cbObj) { + + logger.log(Level.INFO, "RAMAN run()..."); + + callbackObj = cbObj; + addImageDone = false; + cancelled = false; + + addImageTask = new AddImageTask(settings, progressPanel, cbObj); + addImageTask.execute(); + + return; + } + + /*** + @Override + public String[] getErrors() { + + logger.log(Level.INFO, "RAMAN getErrors()..."); + + // RAMAN TBD + return null; + } + *****/ + + @Override + public void cancel() { + + logger.log(Level.INFO, "RAMAN cancelProcessing()..."); + + cancelled = true; + addImageTask.cancelTask(); + + return; + } + + /***** + @Override + public List getNewContents() { + return addImageTask.getNewContents(); + } + * *****/ + + + private static class CurrentDirectoryFetcher extends SwingWorker { + + //AddImageWizardIngestConfigPanel.AddImageTask task; + JProgressBar progressBar; + AddImageWizardAddingProgressVisual progressVisual; + SleuthkitJNI.CaseDbHandle.AddImageProcess process; + + CurrentDirectoryFetcher(JProgressBar aProgressBar, AddImageWizardAddingProgressVisual wiz, SleuthkitJNI.CaseDbHandle.AddImageProcess proc) { + this.progressVisual = wiz; + this.process = proc; + this.progressBar = aProgressBar; + } + + /** + * @return the currently processing directory + */ + @Override + protected Integer doInBackground() { + try { + while (progressBar.getValue() < 100 || progressBar.isIndeterminate()) { //TODO Rely on state variable in AddImgTask class + + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + progressVisual.setCurrentDirText(process.currentDirectory()); + } + }); + + Thread.sleep(2 * 1000); + } + return 1; + } catch (InterruptedException ie) { + return -1; + } + } + } + + + private class AddImageTask extends SwingWorker { + + private JProgressBar progressBar; + 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 String errorString = null; + private List errorList = new ArrayList(); + + private WizardDescriptor wizDescriptor; + + private Logger logger = Logger.getLogger(AddImageTask.class.getName()); + private AddImageWizardAddingProgressPanel progressPanel; + private DSPCallback callbackObj; + + private final List newContents = Collections.synchronizedList(new ArrayList()); + + private SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess; + + protected AddImageTask(WizardDescriptor settings, AddImageWizardAddingProgressPanel aProgressPanel, DSPCallback cbObj ) { + this.progressPanel = aProgressPanel; + this.progressBar = progressPanel.getComponent().getProgressBar(); + currentCase = Case.getCurrentCase(); + + this.callbackObj = cbObj; + this.wizDescriptor = settings; + } + + /** + * Starts the addImage process, but does not commit the results. + * + * @return + * + * @throws Exception + */ + @Override + protected Integer doInBackground() { + + logger.log(Level.INFO, "RAMAN: doInBackground()"); + + this.setProgress(0); + + errorList.clear(); + + /**** RAMAN TBD: a higher level caller should set up the cleanup task and then call DataSourceHandler.cancelProcessing() + * + // Add a cleanup task to interrupt the backgroud process if the + // wizard exits while the background process is running. + AddImageAction.CleanupTask cancelledWhileRunning = action.new CleanupTask() { + @Override + void cleanup() throws Exception { + logger.log(Level.INFO, "Add image process interrupted."); + addImageTask.interrupt(); //it might take time to truly interrupt + } + }; + * *************************/ + + + 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; + } + + + String dataSourcePath = (String) wizDescriptor.getProperty(AddImageAction.DATASOURCEPATH_PROP); + String dataSourceType = (String) wizDescriptor.getProperty(AddImageAction.DATASOURCETYPE_PROP); + String timeZone = wizDescriptor.getProperty(AddImageAction.TIMEZONE_PROP).toString(); + boolean noFatOrphans = ((Boolean) wizDescriptor.getProperty(AddImageAction.NOFATORPHANS_PROP)).booleanValue(); + + + addImageProcess = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans); + fetcher = new CurrentDirectoryFetcher(this.progressBar, progressPanel.getComponent(), addImageProcess); + //RAMAN TBD: handle the cleanup task + //cancelledWhileRunning.enable(); + try { + progressPanel.setStateStarted(); + fetcher.execute(); + addImageProcess.run(new String[]{dataSourcePath}); + } 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; + //errorString = ex.getMessage(); + errorList.add(ex.getMessage()); + } catch (TskDataException ex) { + logger.log(Level.WARNING, "Data errors occurred while running add image. ", ex); + //errorString = ex.getMessage(); + errorList.add(ex.getMessage()); + } finally { + // process is over, doesn't need to be dealt with if cancel happens + //RAMAN TBD: handle the cleanup task + //cancelledWhileRunning.disable(); + + } + + 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(WizardDescriptor settings) throws Exception { + + logger.log(Level.INFO, "RAMAN: commitImage()..."); + + String contentPath = (String) settings.getProperty(AddImageAction.DATASOURCEPATH_PROP); + + String timezone = settings.getProperty(AddImageAction.TIMEZONE_PROP).toString(); + settings.putProperty(AddImageAction.IMAGEID_PROP, ""); + + 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(contentPath, 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); + //progressPanel.addErrors(verificationErrors, false); + } + + /*** RAMAN TBD: how to handle the newContent notification back to IngestConfigPanel **/ + newContents.add(newImage); + + settings.putProperty(AddImageAction.IMAGEID_PROP, imageId); + } + + // Can't bail and revert image add after commit, so disable image cleanup + // task + + // RAMAN TBD: cleanup task should be handled by the caller + // cleanupImage.disable(); + + settings.putProperty(AddImageAction.IMAGECLEANUPTASK_PROP, null); + + 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. + */ + @Override + protected void done() { + + logger.log(Level.INFO, "RAMAN: done()..."); + + //these are required to stop the CurrentDirectoryFetcher + progressBar.setIndeterminate(false); + setProgress(100); + + 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 (hasCritError) { + //core error + // RAMAN TBD: Error reporting needs to be removed from here. All errors are returned to caller directly. + //progressPanel.addErrors(errorString, true); + } + // Do not return yet. Callback must be called + } + if (!errorList.isEmpty()) { + //data error (non-critical) + logger.log(Level.INFO, "Handling non-critical errors that occured in add image process"); + + // RAMAN TBD: Error reporting needs to be removed from here. All errors are returned to caller directly. + //progressPanel.addErrors(errorString, false); + } + + // When everything happens without an error: + if (!(cancelled || hasCritError)) { + + try { + + + /* ***************************** + * RAMAN TBD: the caller needs to handle the cleanup ??? + // the add-image process needs to be reverted if the wizard doesn't finish + cleanupImage = action.new CleanupTask() { + //note, CleanupTask runs inside EWT thread + @Override + void cleanup() throws Exception { + logger.log(Level.INFO, "Running cleanup task after add image process"); + revert(); + } + }; + cleanupImage.enable(); + * ************************/ + + //if (errorString == null) { // complete progress bar + if (errorList.isEmpty() ) { // complete progress bar + progressPanel.getComponent().setProgressBarTextAndColor("*Data Source added.", 100, Color.black); + } + + // RAMAN TBD: this should not be happening in here - caller should do this + + // Get attention for the process finish + java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP! + AddImageWizardAddingProgressVisual panel = progressPanel.getComponent(); + if (panel != null) { + Window w = SwingUtilities.getWindowAncestor(panel); + if (w != null) { + w.toFront(); + } + } + + // Tell the panel we're done + progressPanel.setStateFinished(); + + + if (newContents.isEmpty()) { + if (addImageProcess != null) { // and if we're done configuring ingest + // commit anything + try { + commitImage(wizDescriptor); + } catch (Exception ex) { + // 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."); + + } + + + + + // Start ingest if we can + // RAMAN TBD - remove this from here + //startIngest(); + + } catch (Exception ex) { + //handle unchecked exceptions post image add + + logger.log(Level.WARNING, "Unexpected errors occurred while running post add image cleanup. ", ex); + + progressPanel.getComponent().setProgressBarTextAndColor("*Failed to add image.", 0, Color.black); // set error message + + // Log error/display warning + + logger.log(Level.SEVERE, "Error adding image to case", ex); + } finally { + + + } + } + + // invoke the callBack, unless the caller cancelled + if (!cancelled) + doCallBack(); + + } + + + void doCallBack() + { + logger.log(Level.INFO, "RAMAN In 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; + } + + callbackObj.done(result, errorList, newContents); + } + + /***** + public List getNewContents() { + + return newContents; + + } + * ********/ + + void cancelTask() { + + logger.log(Level.INFO, "RAMAN: 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..."); + } + } + } + void interrupt() throws Exception { + + logger.log(Level.INFO, "RAMAN: interrupt()..."); + + //interrupted = true; + 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); + } + } + + //runs in EWT + void revert() { + + logger.log(Level.INFO, "RAMAN: 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/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java index a71ad31681..3bc25fe42d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java @@ -158,8 +158,8 @@ public class ImageFilePanel extends ContentTypePanel implements DocumentListener } @Override - public ContentType getContentType() { - return ContentType.IMAGE; + public String getContentType() { + return "IMAGE"; } @Override diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java index 6a51382940..f007189683 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java @@ -153,8 +153,8 @@ public class LocalDiskPanel extends ContentTypePanel { } @Override - public ContentType getContentType() { - return ContentType.DISK; + public String getContentType() { + return "DISK"; } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java index 7d07033ac1..4af5cf0ab9 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java @@ -79,8 +79,8 @@ public class LocalFilesPanel extends ContentTypePanel { } @Override - public ContentType getContentType() { - return ContentType.LOCAL; + public String getContentType() { + return "LOCAL"; } @Override From 7000ab6865499dd0c72430ee6fc1ac9fb9f5d455 Mon Sep 17 00:00:00 2001 From: raman-bt Date: Tue, 15 Oct 2013 11:31:30 -0400 Subject: [PATCH 02/21] Define DSPProgressMoinitor class. Eliminate dependency on the ProgressControlPanel from DataSourceProcessor. --- .../AddImageWizardAddingProgressPanel.java | 23 ++ .../AddImageWizardIngestConfigPanel.java | 31 ++- .../casemodule/DataSourceProcessor.java | 4 +- .../autopsy/casemodule/ImageDSProcessor.java | 196 +++++++----------- 4 files changed, 118 insertions(+), 136 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java index 7b0faf13f8..3817565c54 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java @@ -50,6 +50,29 @@ class AddImageWizardAddingProgressPanel implements WizardDescriptor.FinishablePa private AddImageWizardAddingProgressVisual component; private final Set listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0 + private DSPProgressMonitorImpl dspProgressMonitorImpl = new DSPProgressMonitorImpl(); + + public DSPProgressMonitorImpl getDSPProgressMonitorImpl() { + return dspProgressMonitorImpl; + } + + private class DSPProgressMonitorImpl implements DSPProgressMonitor { + @Override + public void setIndeterminate(boolean indeterminate) { + getComponent().getProgressBar().setIndeterminate(indeterminate); + + } + @Override + public void setProgress(int progress) { + getComponent().getProgressBar().setValue(progress); + } + @Override + public void setText(String text) { + getComponent().setCurrentDirText(text); + + } + + } /** * Get the visual component for the panel. In this template, the component * is kept separate. This can be more efficient: if the wizard is created diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java index dab6bf7318..5a89aa2997 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java @@ -275,8 +275,11 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel errList, List contents) { logger.log(Level.INFO, "RAMAN dataSourceProcessorDone()."); - // RAMAN TBD - // check if there is any new content and kick off ingest.... - - // RAMAN TBD: check the result - - // RAMAN TBD: if errors, display them on the progress panel - - // disbale the cleanup task + // disable the cleanup task cleanupTask.disable(); + + //check the result and display to user + if (result == DSPCallback.DSP_Result.NO_ERRORS) + progressPanel.getComponent().setProgressBarTextAndColor("*Data Source added.", 100, Color.black); + else + progressPanel.getComponent().setProgressBarTextAndColor("*Errors encountered in adding Data Source.", 100, Color.red); + + + //if errors, display them on the progress panel + for ( String err: errList ) { + // TBD: there should be an error level for each error + progressPanel.addErrors(err, false); + } + newContents.clear(); @@ -307,6 +317,9 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel { - - //AddImageWizardIngestConfigPanel.AddImageTask task; - JProgressBar progressBar; - AddImageWizardAddingProgressVisual progressVisual; - SleuthkitJNI.CaseDbHandle.AddImageProcess process; - - CurrentDirectoryFetcher(JProgressBar aProgressBar, AddImageWizardAddingProgressVisual wiz, SleuthkitJNI.CaseDbHandle.AddImageProcess proc) { - this.progressVisual = wiz; - this.process = proc; - this.progressBar = aProgressBar; - } - - /** - * @return the currently processing directory - */ - @Override - protected Integer doInBackground() { - try { - while (progressBar.getValue() < 100 || progressBar.isIndeterminate()) { //TODO Rely on state variable in AddImgTask class - - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - progressVisual.setCurrentDirText(process.currentDirectory()); - } - }); - - Thread.sleep(2 * 1000); - } - return 1; - } catch (InterruptedException ie) { - return -1; - } - } - } - + private class AddImageTask extends SwingWorker { - private JProgressBar progressBar; 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 boolean addImageDone = false; - - //private String errorString = null; private List errorList = new ArrayList(); private WizardDescriptor wizDescriptor; private Logger logger = Logger.getLogger(AddImageTask.class.getName()); - private AddImageWizardAddingProgressPanel progressPanel; + private DSPProgressMonitor progressMonitor; private DSPCallback callbackObj; private final List newContents = Collections.synchronizedList(new ArrayList()); private SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess; + private CurrentDirectoryFetcher fetcher; + - protected AddImageTask(WizardDescriptor settings, AddImageWizardAddingProgressPanel aProgressPanel, DSPCallback cbObj ) { - this.progressPanel = aProgressPanel; - this.progressBar = progressPanel.getComponent().getProgressBar(); + + private class CurrentDirectoryFetcher extends SwingWorker { + + DSPProgressMonitor progressMonitor; + SleuthkitJNI.CaseDbHandle.AddImageProcess process; + + CurrentDirectoryFetcher(DSPProgressMonitor aProgressMonitor, SleuthkitJNI.CaseDbHandle.AddImageProcess proc) { + this.progressMonitor = aProgressMonitor; + this.process = proc; + // this.progressBar = aProgressBar; + } + + /** + * @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(WizardDescriptor settings, DSPProgressMonitor aProgressMonitor, DSPCallback cbObj ) { + this.progressMonitor = aProgressMonitor; currentCase = Case.getCurrentCase(); this.callbackObj = cbObj; @@ -223,18 +218,6 @@ public class ImageDSProcessor implements DataSourceProcessor { errorList.clear(); - /**** RAMAN TBD: a higher level caller should set up the cleanup task and then call DataSourceHandler.cancelProcessing() - * - // Add a cleanup task to interrupt the backgroud process if the - // wizard exits while the background process is running. - AddImageAction.CleanupTask cancelledWhileRunning = action.new CleanupTask() { - @Override - void cleanup() throws Exception { - logger.log(Level.INFO, "Add image process interrupted."); - addImageTask.interrupt(); //it might take time to truly interrupt - } - }; - * *************************/ try { @@ -263,27 +246,24 @@ public class ImageDSProcessor implements DataSourceProcessor { addImageProcess = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans); - fetcher = new CurrentDirectoryFetcher(this.progressBar, progressPanel.getComponent(), addImageProcess); - //RAMAN TBD: handle the cleanup task - //cancelledWhileRunning.enable(); + fetcher = new CurrentDirectoryFetcher(progressMonitor, addImageProcess); + try { - progressPanel.setStateStarted(); + progressMonitor.setIndeterminate(true); + progressMonitor.setProgress(0); + fetcher.execute(); addImageProcess.run(new String[]{dataSourcePath}); } 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; - //errorString = ex.getMessage(); errorList.add(ex.getMessage()); } catch (TskDataException ex) { logger.log(Level.WARNING, "Data errors occurred while running add image. ", ex); - //errorString = ex.getMessage(); - errorList.add(ex.getMessage()); + errorList.add(ex.getMessage()); } finally { // process is over, doesn't need to be dealt with if cancel happens - //RAMAN TBD: handle the cleanup task - //cancelledWhileRunning.disable(); } @@ -327,20 +307,19 @@ public class ImageDSProcessor implements DataSourceProcessor { if (verificationErrors.equals("") == false) { //data error (non-critical) errorList.add(verificationErrors); - //progressPanel.addErrors(verificationErrors, false); } - /*** RAMAN TBD: how to handle the newContent notification back to IngestConfigPanel **/ + // newContents.add(newImage); + // RAMAN TBD: imageID should be return via the callback settings.putProperty(AddImageAction.IMAGEID_PROP, imageId); } // Can't bail and revert image add after commit, so disable image cleanup // task - // RAMAN TBD: cleanup task should be handled by the caller - // cleanupImage.disable(); + settings.putProperty(AddImageAction.IMAGECLEANUPTASK_PROP, null); @@ -360,10 +339,11 @@ public class ImageDSProcessor implements DataSourceProcessor { protected void done() { logger.log(Level.INFO, "RAMAN: done()..."); - - //these are required to stop the CurrentDirectoryFetcher - progressBar.setIndeterminate(false); + setProgress(100); + + // cancel + fetcher.cancel(true); addImageDone = true; @@ -372,19 +352,13 @@ public class ImageDSProcessor implements DataSourceProcessor { if (cancelled || hasCritError) { logger.log(Level.INFO, "Handling errors or interruption that occured in add image process"); revert(); - if (hasCritError) { - //core error - // RAMAN TBD: Error reporting needs to be removed from here. All errors are returned to caller directly. - //progressPanel.addErrors(errorString, true); - } // Do not return yet. Callback must be called } if (!errorList.isEmpty()) { - //data error (non-critical) + logger.log(Level.INFO, "Handling non-critical errors that occured in add image process"); - // RAMAN TBD: Error reporting needs to be removed from here. All errors are returned to caller directly. - //progressPanel.addErrors(errorString, false); + // error are returned back to the caller } // When everything happens without an error: @@ -393,28 +367,14 @@ public class ImageDSProcessor implements DataSourceProcessor { try { - /* ***************************** - * RAMAN TBD: the caller needs to handle the cleanup ??? - // the add-image process needs to be reverted if the wizard doesn't finish - cleanupImage = action.new CleanupTask() { - //note, CleanupTask runs inside EWT thread - @Override - void cleanup() throws Exception { - logger.log(Level.INFO, "Running cleanup task after add image process"); - revert(); - } - }; - cleanupImage.enable(); - * ************************/ + - //if (errorString == null) { // complete progress bar - if (errorList.isEmpty() ) { // complete progress bar - progressPanel.getComponent().setProgressBarTextAndColor("*Data Source added.", 100, Color.black); - } + // RAMAN TBD: this should not be happening in here - caller should do this // Get attention for the process finish + /****** java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP! AddImageWizardAddingProgressVisual panel = progressPanel.getComponent(); if (panel != null) { @@ -423,9 +383,10 @@ public class ImageDSProcessor implements DataSourceProcessor { w.toFront(); } } + * *******/ // Tell the panel we're done - progressPanel.setStateFinished(); + progressMonitor.setProgress(100); if (newContents.isEmpty()) { @@ -434,6 +395,7 @@ public class ImageDSProcessor implements DataSourceProcessor { try { commitImage(wizDescriptor); } catch (Exception ex) { + errorList.add(ex.getMessage()); // Log error/display warning logger.log(Level.SEVERE, "Error adding image to case.", ex); } @@ -442,28 +404,19 @@ public class ImageDSProcessor implements DataSourceProcessor { } } - else //already commited? - { + else { //already commited? logger.log(Level.INFO, "Assuming image already committed, will not commit."); - } - - // Start ingest if we can - // RAMAN TBD - remove this from here - //startIngest(); - } 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); - - progressPanel.getComponent().setProgressBarTextAndColor("*Failed to add image.", 0, Color.black); // set error message - - // Log error/display warning - + logger.log(Level.SEVERE, "Error adding image to case", ex); } finally { @@ -497,13 +450,6 @@ public class ImageDSProcessor implements DataSourceProcessor { callbackObj.done(result, errorList, newContents); } - /***** - public List getNewContents() { - - return newContents; - - } - * ********/ void cancelTask() { From a3a027eea0bc065918e70f6a3a19d9336c3f251c Mon Sep 17 00:00:00 2001 From: raman-bt Date: Wed, 16 Oct 2013 08:14:17 -0400 Subject: [PATCH 03/21] New file, DSPProgressMonitor.java - that got missed in the the previous commit. --- .../casemodule/DSPProgressMonitor.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/DSPProgressMonitor.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/DSPProgressMonitor.java b/Core/src/org/sleuthkit/autopsy/casemodule/DSPProgressMonitor.java new file mode 100644 index 0000000000..d3acea384c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/DSPProgressMonitor.java @@ -0,0 +1,19 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.casemodule; + +/* + * An GUI agnostic DSPProgressMonitor interface for DataSorceProcesssors to + * indicate progress. + * It models after a JProgressbar though could use any underlying implementation + */ +public interface DSPProgressMonitor { + + void setIndeterminate(boolean indeterminate); + + void setProgress(int progress); + + void setText(String text); +} From 9ed39d665d84815996159ba1b2d813733c798e09 Mon Sep 17 00:00:00 2001 From: raman-bt Date: Thu, 17 Oct 2013 09:49:18 -0400 Subject: [PATCH 04/21] Eliminate ContentTypePanel. DataSourceProcessor returns a JPanel instead. --- .../AddImageWizardChooseDataSourcePanel.java | 7 +- .../AddImageWizardChooseDataSourceVisual.form | 2 +- .../AddImageWizardChooseDataSourceVisual.java | 190 ++++++------------ .../sleuthkit/autopsy/casemodule/Case.java | 2 + .../autopsy/casemodule/ContentTypePanel.java | 56 +++--- .../casemodule/DataSourceProcessor.java | 10 +- .../autopsy/casemodule/ImageDSProcessor.java | 98 ++++++++- .../autopsy/casemodule/ImageFilePanel.java | 20 +- .../autopsy/casemodule/LocalDiskPanel.java | 16 +- .../autopsy/casemodule/LocalFilesPanel.java | 15 +- .../casemodule/MissingImageDialog.java | 57 +++--- 11 files changed, 244 insertions(+), 229 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java index 7fb2a69b0b..2e103d3272 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java @@ -183,10 +183,12 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java index b20d43e3b2..3595667230 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java @@ -19,6 +19,8 @@ package org.sleuthkit.autopsy.casemodule; import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; @@ -27,6 +29,7 @@ import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.SimpleTimeZone; import java.util.TimeZone; import java.util.logging.Level; @@ -35,8 +38,6 @@ import javax.swing.JPanel; import javax.swing.event.DocumentEvent; import javax.swing.event.ListDataListener; import org.openide.util.Lookup; -import org.sleuthkit.autopsy.casemodule.ContentTypePanel; -//import org.sleuthkit.autopsy.casemodule.ContentTypePanel.ContentType; import org.sleuthkit.autopsy.coreutils.Logger; /** @@ -67,11 +68,10 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { static final String allDesc = "All Supported Types"; static GeneralFilter allFilter = new GeneralFilter(allExt, allDesc); private AddImageWizardChooseDataSourcePanel wizPanel; - private ContentTypeModel model; - private ContentTypePanel currentPanel; + private JPanel currentPanel; - static private Map datasourceProcessorsMap = new HashMap();; - + private Map datasourceProcessorsMap = new HashMap(); + /** @@ -88,60 +88,62 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { private void customInit() { - discoverDataSourceProcessors(); - model = new ContentTypeModel(); - typeComboBox.setModel(model); + // set up the DSP type combobox + typeComboBox.removeAllItems(); + Set dspTypes = datasourceProcessorsMap.keySet(); + for(String dspType:dspTypes){ + typeComboBox.addItem(dspType); + } + + //add actionlistner to listen for change + ActionListener cbActionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dspSelectionChanged(); + + } + }; + + typeComboBox.addActionListener(cbActionListener); + typeComboBox.setSelectedIndex(0); typePanel.setLayout(new BorderLayout()); - //updateCurrentPanel(ImageFilePanel.getDefault()); - updateCurrentPanel(model.getElementAt(0)); + updateCurrentPanel(GetCurrentDSProcessor().getPanel()); } private void discoverDataSourceProcessors() { - - //datasourceHandlersMap.clear(); + logger.log(Level.INFO, "RAMAN discoverDataSourceProcessors()..."); - - // RAMAN TBD: hack for now - { - //ContentTypePanel.RegisterPanel(ImageFilePanel.getDefault()); - //ContentTypePanel.RegisterPanel(LocalDiskPanel.getDefault()); - //ContentTypePanel.RegisterPanel(LocalFilesPanel.getDefault()); - } - + for (DataSourceProcessor dsProcessor: Lookup.getDefault().lookupAll(DataSourceProcessor.class)) { - - logger.log(Level.INFO, "RAMAN discoverDataSourceHandlers(): found an instance of DataSourceHandler"); - - - String dsType = dsProcessor.getType(); - JPanel panel = dsProcessor.getPanel(); - String validate = dsProcessor.validatePanel(); - //dshandler.run(null); - //String[] errors = dshandler.getErrors(); - + logger.log(Level.INFO, "RAMAN discoverDataSourceProcessors()L found a DSP for type = " + dsProcessor.getType() ); + if (!datasourceProcessorsMap.containsKey(dsProcessor.getType()) ) { - - // Regsiter the panel for the discovered DS handler here - ContentTypePanel.RegisterPanel(dsProcessor.getPanel()); - - datasourceProcessorsMap.put(dsProcessor.getType(), dsProcessor); - } - + if (!datasourceProcessorsMap.containsKey(dsProcessor.getType()) ) { + datasourceProcessorsMap.put(dsProcessor.getType(), dsProcessor); + } + else { + logger.log(Level.SEVERE, "RAMAN discoverDataSourceProcessors(): A DataSourceProcessor already exisits for type = " + dsProcessor.getType() ); + } + } } - - - } + } + private void dspSelectionChanged() { + // update the current panel to selection + currentPanel = GetCurrentDSProcessor().getPanel(); + updateCurrentPanel(currentPanel); + } + /** * Changes the current panel to the given panel. * * @param panel instance of ImageTypePanel to change to */ - private void updateCurrentPanel(ContentTypePanel panel) { + private void updateCurrentPanel(JPanel panel) { currentPanel = panel; typePanel.removeAll(); typePanel.add((JPanel) currentPanel, BorderLayout.CENTER); @@ -158,8 +160,12 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { } } }); - currentPanel.select(); - if (currentPanel.getContentType().equals("LOCAL")) { + + + /* RAMAN TBD: this should all be ripped from here. the content specific UI elements should all go + * into the corresponding DSP + */ + if (GetCurrentDSProcessor().getType().equals("LOCAL")) { //disable image specific options noFatOrphansCheckbox.setEnabled(false); descLabel.setEnabled(false); @@ -173,18 +179,13 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { } /** - * Returns the currently selected DS handler in the combobox - * - * - * @return name the name of this panel + * Returns the currently selected DS Processor + * @return DataSourceProcessor the DataSourceProcessor corresponding to the data source type selected in the combobox */ public DataSourceProcessor GetCurrentDSProcessor() { - - logger.log(Level.INFO, "RAMAN GetCurrentDSProcessor()..."); // get the type of the currently selected panel and then look up // the correspodning DS Handler in the map - String dsType = currentPanel.getContentType(); - + String dsType = (String) typeComboBox.getSelectedItem(); DataSourceProcessor dsProcessor = datasourceProcessorsMap.get(dsType); return dsProcessor; @@ -202,44 +203,11 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { return "Enter Data Source Information"; } - /** - * Gets the data sources path from the Image Path Text Field. - * - * @return data source path, can be comma separated for multiples - */ - public String getContentPaths() { - return currentPanel.getContentPaths(); - } - - /** - * Gets the data sources type selected - * - * @return data source selected - */ - public String getContentType() { - return currentPanel.getContentType(); - } - - /** - * Reset the data sources panel selected - */ - public void reset() { - currentPanel.reset(); - } - - /** - * Sets the image path of the current panel. - * - * @param s the image path to set - */ - public void setContentPath(String s) { - currentPanel.setContentPath(s); - } - /** * * @return true if no fat orphans processing is selected */ + /***RAMAN TBD: move this into DSP ****/ boolean getNoFatOrphans() { return noFatOrphansCheckbox.isSelected(); } @@ -249,6 +217,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { * * @return timeZone the time zone that selected */ + /***RAMAN TBD: move this into the DSP****/ public String getSelectedTimezone() { String tz = timeZoneComboBox.getSelectedItem().toString(); return tz.substring(tz.indexOf(")") + 2).trim(); @@ -259,6 +228,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { * Creates the drop down list for the time zones and then makes the local * machine time zones to be selected. */ + /*** RAMAN TBD: move this into the DSP panel ***/ public void createTimeZoneList() { // load and add all timezone String[] ids = SimpleTimeZone.getAvailableIDs(); @@ -309,7 +279,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { inputPanel = new javax.swing.JPanel(); typeTabel = new javax.swing.JLabel(); typePanel = new javax.swing.JPanel(); - typeComboBox = new javax.swing.JComboBox(); + typeComboBox = new javax.swing.JComboBox(); imgInfoLabel = new javax.swing.JLabel(); org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.jLabel2.text")); // NOI18N @@ -428,7 +398,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { private javax.swing.JCheckBox noFatOrphansCheckbox; private javax.swing.JComboBox timeZoneComboBox; private javax.swing.JLabel timeZoneLabel; - private javax.swing.JComboBox typeComboBox; + private javax.swing.JComboBox typeComboBox; private javax.swing.JPanel typePanel; private javax.swing.JLabel typeTabel; // End of variables declaration//GEN-END:variables @@ -442,44 +412,12 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { * @param e the document event */ public void updateUI(DocumentEvent e) { - this.wizPanel.enableNextButton(currentPanel.enableNext()); + // Enable the Next button if the current DSP panel is valid + String err = GetCurrentDSProcessor().validatePanel(); + if (null == err) + this.wizPanel.enableNextButton(true); + else + this.wizPanel.enableNextButton(false); } - /** - * ComboBoxModel to control typeComboBox and supply ImageTypePanels. - */ - private class ContentTypeModel implements ComboBoxModel { - - private ContentTypePanel selected; - private ContentTypePanel[] types = ContentTypePanel.getPanels(); - - @Override - public void setSelectedItem(Object anItem) { - selected = (ContentTypePanel) anItem; - updateCurrentPanel(selected); - } - - @Override - public Object getSelectedItem() { - return selected; - } - - @Override - public int getSize() { - return types.length; - } - - @Override - public ContentTypePanel getElementAt(int index) { - return types[index]; - } - - @Override - public void addListDataListener(ListDataListener l) { - } - - @Override - public void removeListDataListener(ListDataListener l) { - } - } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 29151bc6ea..caa833e8aa 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -319,7 +319,9 @@ public class Case implements SleuthkitCase.ErrorObserver { + "\nPlease note that you will still be able to browse directories and generate reports\n" + "if you choose No, but you will not be able to view file content or run the ingest process.", "Missing Image", JOptionPane.YES_NO_OPTION); if (ret == JOptionPane.YES_OPTION) { + /***** RAMAN TBD: MissingImageDialog class needs to be refactored to eliminate ContentTypePanel dependency. MissingImageDialog.makeDialog(obj_id, db); + * *****************/ } else { logger.log(Level.WARNING, "Selected image files don't match old files!"); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ContentTypePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ContentTypePanel.java index 4b2f4aada8..ab144723b1 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ContentTypePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ContentTypePanel.java @@ -23,6 +23,7 @@ import javax.swing.JPanel; import java.util.ArrayList; import java.util.List; +/************ abstract class ContentTypePanel extends JPanel { // Collection of panels that are dynamically discovered and registered @@ -41,10 +42,10 @@ abstract class ContentTypePanel extends JPanel { private String contentType; - /** - * Returns a list off all the panels extending ImageTypePanel. - * @return list of all ImageTypePanels - */ +// +// * Returns a list off all the panels extending ImageTypePanel. +// * @return list of all ImageTypePanels +// public static ContentTypePanel[] getPanels() { //return new ContentTypePanel[] {ImageFilePanel.getDefault(), LocalDiskPanel.getDefault(), LocalFilesPanel.getDefault() }; @@ -55,40 +56,41 @@ abstract class ContentTypePanel extends JPanel { return registeredPanels.toArray(new ContentTypePanel[registeredPanels.size()]); } - /** - * Return the path of the selected content in this panel. - * @return paths to selected content (one or more if multiselect supported) - */ +// +// * Return the path of the selected content in this panel. +// * @return paths to selected content (one or more if multiselect supported) +// abstract public String getContentPaths(); - /** - * Set the selected content in this panel to the provided path. - * This function is optional. - * @param s path to selected content - */ +// +// * Set the selected content in this panel to the provided path. +// * This function is optional. +// * @param s path to selected content +// abstract public void setContentPath(String s); - /** - * Get content type (image, disk, local file) of the source this wizard panel is for - * @return ContentType of the source panel - */ +// +// * Get content type (image, disk, local file) of the source this wizard panel is for +// * @return ContentType of the source panel +// abstract public String getContentType(); - /** - * Returns if the next button should be enabled in the current wizard. - * @return true if the next button should be enabled, false otherwise - */ +// +// * Returns if the next button should be enabled in the current wizard. +// * @return true if the next button should be enabled, false otherwise +// abstract public boolean enableNext(); - /** - * Tells this panel to reset itself - */ +// +// * Tells this panel to reset itself +// abstract public void reset(); - /** - * Tells this panel it has been selected. - */ +// +// * Tells this panel it has been selected. +// abstract public void select(); } +***************/ \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/DataSourceProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/DataSourceProcessor.java index 81b8b21aa0..76f9b89f4e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/DataSourceProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/DataSourceProcessor.java @@ -22,7 +22,6 @@ import java.util.List; import javax.swing.JPanel; import org.openide.WizardDescriptor; import org.sleuthkit.autopsy.casemodule.DSPProgressMonitor; -import org.sleuthkit.autopsy.casemodule.ContentTypePanel; import org.sleuthkit.datamodel.Content; public interface DataSourceProcessor { @@ -43,7 +42,7 @@ public interface DataSourceProcessor { * Returns the picker panel to be displayed along with any other * runtime options supported by the data source handler. **/ - ContentTypePanel getPanel(); + JPanel getPanel(); /** * Called to validate the input data in the panel. @@ -80,8 +79,11 @@ public interface DataSourceProcessor { **/ void cancel(); - - + /** + * Called to reset/reinit the DSP. + * + **/ + void reset(); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java index 9025379972..696f903f4e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java @@ -45,6 +45,14 @@ public class ImageDSProcessor implements DataSourceProcessor { DSPCallback callbackObj = null; + // set to TRUE if the image options have been set via API and config Jpanel should be ignored + private boolean imageOptionsSet = false; + private String imagePath; + private String timeZone; + private boolean noFatOrphans; + + + public ImageDSProcessor() { logger.log(Level.INFO, "RAMAN ImageDSHandler()..."); @@ -72,9 +80,11 @@ public class ImageDSProcessor implements DataSourceProcessor { @Override - public ContentTypePanel getPanel() { + public JPanel getPanel() { logger.log(Level.INFO, "RAMAN getPanel()..."); + + // RAMAN TBD: we should preload the panel with any saved settings return imageFilePanel; } @@ -83,9 +93,11 @@ public class ImageDSProcessor implements DataSourceProcessor { public String validatePanel() { logger.log(Level.INFO, "RAMAN validatePanel()..."); - - return null; - + + if (imageFilePanel.validatePanel() ) + return null; + else + return "Error in panel"; } @Override @@ -96,7 +108,26 @@ public class ImageDSProcessor implements DataSourceProcessor { callbackObj = cbObj; cancelled = false; + if (!imageOptionsSet) + { + // get the image options from the panel + imagePath = imageFilePanel.getContentPaths(); + + /*** RAMAN TBD: get the TZ and NoFatOrhpns options from the config panel ******/ + //timeZone = imageFilePanel.getTimeZone(); + //noFatOrphans = imageFilePanel.getNoFatOrphans(); + + + + } + addImageTask = new AddImageTask(settings, progressMonitor, cbObj); + + /**** RAMAN TBD: set other params needed by AddImageTask - such as TZ and NoFatOrhpans **/ + addImageTask.SetImageOptions(imagePath); + + + addImageTask.execute(); return; @@ -130,9 +161,34 @@ public class ImageDSProcessor implements DataSourceProcessor { return addImageTask.getNewContents(); } * *****/ - - + @Override + public void reset() { + + logger.log(Level.INFO, "RAMAN reset()..."); + + // reset the config panel + imageFilePanel.reset(); + + // reset state + imageOptionsSet = false; + imagePath = null; + timeZone = null; + noFatOrphans = false; + + return; + } + + public void SetDataSourceOptions(String imgPath, String tz, boolean noFat) { + + this.imagePath = imgPath; + this.timeZone = tz; + this.noFatOrphans = noFat; + + imageOptionsSet = true; + + } + private class AddImageTask extends SwingWorker { @@ -157,6 +213,20 @@ public class ImageDSProcessor implements DataSourceProcessor { private SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess; private CurrentDirectoryFetcher fetcher; + private String imagePath; + private String dataSourcetype; + String timeZone; + boolean noFatOrphans; + + + + public void SetImageOptions(String imgPath) { + this.imagePath = imgPath; + + // RAMAN TBD: also set TZ and noFatOrphans + // this.timeZone = tz; + // this.noFatOrphans = noFatOrphans; + } private class CurrentDirectoryFetcher extends SwingWorker { @@ -239,10 +309,16 @@ public class ImageDSProcessor implements DataSourceProcessor { } - String dataSourcePath = (String) wizDescriptor.getProperty(AddImageAction.DATASOURCEPATH_PROP); - String dataSourceType = (String) wizDescriptor.getProperty(AddImageAction.DATASOURCETYPE_PROP); - String timeZone = wizDescriptor.getProperty(AddImageAction.TIMEZONE_PROP).toString(); - boolean noFatOrphans = ((Boolean) wizDescriptor.getProperty(AddImageAction.NOFATORPHANS_PROP)).booleanValue(); + + + + /*** RAMAN TBD: TZ and NoFatOrpjhans should be moved into the Image panel and then should be set by the DSP + * instead of the settings. + * + */ + timeZone = wizDescriptor.getProperty(AddImageAction.TIMEZONE_PROP).toString(); + noFatOrphans = ((Boolean) wizDescriptor.getProperty(AddImageAction.NOFATORPHANS_PROP)).booleanValue(); + addImageProcess = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans); @@ -253,7 +329,7 @@ public class ImageDSProcessor implements DataSourceProcessor { progressMonitor.setProgress(0); fetcher.execute(); - addImageProcess.run(new String[]{dataSourcePath}); + 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 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java index 3bc25fe42d..275c3dced8 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java @@ -26,11 +26,12 @@ import java.util.List; import javax.swing.JFileChooser; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; +import javax.swing.JPanel; /** * ImageTypePanel for adding an image file such as .img, .E0x, .00x, etc. */ -public class ImageFilePanel extends ContentTypePanel implements DocumentListener { +public class ImageFilePanel extends JPanel implements DocumentListener { private static ImageFilePanel instance = null; private PropertyChangeSupport pcs = null; private JFileChooser fc = new JFileChooser(); @@ -144,7 +145,6 @@ public class ImageFilePanel extends ContentTypePanel implements DocumentListener * Get the path of the user selected image. * @return the image path */ - @Override public String getContentPaths() { return pathTextField.getText(); } @@ -152,29 +152,23 @@ public class ImageFilePanel extends ContentTypePanel implements DocumentListener /** * Set the path of the image file. */ - @Override public void setContentPath(String s) { pathTextField.setText(s); } - @Override public String getContentType() { return "IMAGE"; } - @Override public void reset() { //nothing to reset } - - /** * Should we enable the next button of the wizard? * @return true if a proper image has been selected, false otherwise */ - @Override - public boolean enableNext() { + public boolean validatePanel() { String path = getContentPaths(); if (path == null || path.isEmpty()) { return false; @@ -210,18 +204,10 @@ public class ImageFilePanel extends ContentTypePanel implements DocumentListener /** * Set the focus to the pathTextField. */ - @Override public void select() { pathTextField.requestFocusInWindow(); } - /** - * @return the string form of this panel - */ - @Override - public String toString() { - return "Image File"; - } @Override public synchronized void addPropertyChangeListener(PropertyChangeListener pcl) { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java index f007189683..a0ce4ec323 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java @@ -43,7 +43,7 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil; /** * ImageTypePanel for adding a local disk or partition such as PhysicalDrive0 or C:. */ -public class LocalDiskPanel extends ContentTypePanel { +public class LocalDiskPanel extends JPanel { private static LocalDiskPanel instance; private PropertyChangeSupport pcs = null; private List disks = new ArrayList(); @@ -129,7 +129,7 @@ public class LocalDiskPanel extends ContentTypePanel { * Return the currently selected disk path. * @return String selected disk path */ - @Override + //@Override public String getContentPaths() { if(disks.size() > 0) { LocalDisk selected = (LocalDisk) diskComboBox.getSelectedItem(); @@ -143,7 +143,7 @@ public class LocalDiskPanel extends ContentTypePanel { /** * Set the selected disk. */ - @Override + // @Override public void setContentPath(String s) { for(int i=0; i currentFiles = new TreeSet(); //keep currents in a set to disallow duplicates per add @@ -57,7 +58,7 @@ public class LocalFilesPanel extends ContentTypePanel { } - @Override + //@Override public String getContentPaths() { //TODO consider interface change to return list of paths instead @@ -72,28 +73,28 @@ public class LocalFilesPanel extends ContentTypePanel { return b.toString(); } - @Override + //@Override public void setContentPath(String s) { //for the local file panel we don't need to restore the last paths used //when the wizard restarts } - @Override + //@Override public String getContentType() { return "LOCAL"; } - @Override + //@Override public boolean enableNext() { return enableNext; } - @Override + //@Override public void select() { reset(); } - @Override + //@Override public void reset() { currentFiles.clear(); selectedPaths.setText(""); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java index 22d9f11a2f..d734444a57 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java @@ -40,6 +40,8 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; +/**** RAMAN TBD: this class needs to be straightened out. It should not duplicate what the ChooseDataSourceWizard does. + public class MissingImageDialog extends javax.swing.JDialog { private static final Logger logger = Logger.getLogger(MissingImageDialog.class.getName()); long obj_id; @@ -55,12 +57,12 @@ public class MissingImageDialog extends javax.swing.JDialog { customInit(); } - /** - * Client call to create a MissingImageDialog. - * - * @param obj_id obj_id of the missing image - * @param db the current SleuthkitCase connected to a db - */ +// +// * Client call to create a MissingImageDialog. +// * +// * @param obj_id obj_id of the missing image +// * @param db the current SleuthkitCase connected to a db +// static void makeDialog(long obj_id, SleuthkitCase db) { final MissingImageDialog dialog = new MissingImageDialog(obj_id, db); dialog.addWindowListener(new WindowAdapter() { @@ -92,10 +94,10 @@ public class MissingImageDialog extends javax.swing.JDialog { this.setVisible(true); } - /** - * Refresh this panel. - * @param panel current typepanel - */ +// +// * Refresh this panel. +// * @param panel current typepanel +// private void updateCurrentPanel(ContentTypePanel panel) { currentPanel = panel; typePanel.removeAll(); @@ -121,25 +123,25 @@ public class MissingImageDialog extends javax.swing.JDialog { updateSelectButton(); } - /** - * Focuses the select button for easy enter-pressing access. - */ +// +// * Focuses the select button for easy enter-pressing access. +// private void moveFocusToSelect() { this.selectButton.requestFocusInWindow(); } - /** - * Enables/disables the select button based off the current panel. - */ +// +// * Enables/disables the select button based off the current panel. +// private void updateSelectButton() { this.selectButton.setEnabled(currentPanel.enableNext()); } - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ +// +// * This method is called from within the constructor to initialize the form. +// * WARNING: Do NOT modify this code. The content of this method is always +// * regenerated by the Form Editor. +// @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { @@ -293,9 +295,9 @@ public class MissingImageDialog extends javax.swing.JDialog { private javax.swing.JLabel typeTabel; // End of variables declaration//GEN-END:variables - /** - * Verify the user wants to cancel searching for the image. - */ +// +// * Verify the user wants to cancel searching for the image. +// void cancel() { int ret = JOptionPane.showConfirmDialog(null, "No image file has been selected, are you sure you\n" + @@ -306,9 +308,9 @@ public class MissingImageDialog extends javax.swing.JDialog { } } - /** - * ComboBoxModel to control typeComboBox and supply ImageTypePanels. - */ +// +// * ComboBoxModel to control typeComboBox and supply ImageTypePanels. +// private class ImageTypeModel implements ComboBoxModel { ContentTypePanel selected; ContentTypePanel[] types = ContentTypePanel.getPanels(); @@ -343,3 +345,4 @@ public class MissingImageDialog extends javax.swing.JDialog { } } } +********************************/ \ No newline at end of file From 09fb5edba59fff5592cff1c87017d132f8893565 Mon Sep 17 00:00:00 2001 From: raman-bt Date: Thu, 17 Oct 2013 14:17:37 -0400 Subject: [PATCH 05/21] Removed passing of WizardDescriptor across the DataSourceProcessor interface. Moved TZ and NoFatOrphans from ChooseDataSourceVisual panel into the specific DSP panel. --- .../AddImageWizardChooseDataSourcePanel.java | 4 +- .../AddImageWizardChooseDataSourceVisual.form | 60 +- .../AddImageWizardChooseDataSourceVisual.java | 112 +--- .../AddImageWizardIngestConfigPanel.java | 516 +----------------- .../autopsy/casemodule/Bundle.properties | 8 +- .../casemodule/DataSourceProcessor.java | 2 +- .../autopsy/casemodule/ImageDSProcessor.java | 104 +--- .../autopsy/casemodule/ImageFilePanel.form | 61 ++- .../autopsy/casemodule/ImageFilePanel.java | 95 +++- .../netbeans/core/startup/Bundle.properties | 2 +- .../core/windows/view/ui/Bundle.properties | 2 +- 11 files changed, 202 insertions(+), 764 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java index 2e103d3272..777b402eb3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java @@ -228,12 +228,12 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel - - - - - - - - - - @@ -65,16 +55,7 @@ - - - - - - - - - - + @@ -89,41 +70,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -160,7 +106,7 @@ - + @@ -192,7 +138,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java index 3595667230..96440ffd3f 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java @@ -82,7 +82,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { AddImageWizardChooseDataSourceVisual(AddImageWizardChooseDataSourcePanel wizPanel) { initComponents(); this.wizPanel = wizPanel; - createTimeZoneList(); + customInit(); } @@ -161,20 +161,6 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { } }); - - /* RAMAN TBD: this should all be ripped from here. the content specific UI elements should all go - * into the corresponding DSP - */ - if (GetCurrentDSProcessor().getType().equals("LOCAL")) { - //disable image specific options - noFatOrphansCheckbox.setEnabled(false); - descLabel.setEnabled(false); - timeZoneComboBox.setEnabled(false); - } else { - noFatOrphansCheckbox.setEnabled(true); - descLabel.setEnabled(true); - timeZoneComboBox.setEnabled(true); - } updateUI(null); } @@ -203,63 +189,6 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { return "Enter Data Source Information"; } - /** - * - * @return true if no fat orphans processing is selected - */ - /***RAMAN TBD: move this into DSP ****/ - boolean getNoFatOrphans() { - return noFatOrphansCheckbox.isSelected(); - } - - /** - * Gets the time zone that selected on the drop down list. - * - * @return timeZone the time zone that selected - */ - /***RAMAN TBD: move this into the DSP****/ - public String getSelectedTimezone() { - String tz = timeZoneComboBox.getSelectedItem().toString(); - return tz.substring(tz.indexOf(")") + 2).trim(); - } - - // add the timeZone list to the timeZoneComboBox - /** - * Creates the drop down list for the time zones and then makes the local - * machine time zones to be selected. - */ - /*** RAMAN TBD: move this into the DSP panel ***/ - public void createTimeZoneList() { - // load and add all timezone - String[] ids = SimpleTimeZone.getAvailableIDs(); - for (String id : ids) { - TimeZone zone = TimeZone.getTimeZone(id); - int offset = zone.getRawOffset() / 1000; - int hour = offset / 3600; - int minutes = (offset % 3600) / 60; - String item = String.format("(GMT%+d:%02d) %s", hour, minutes, id); - - /* - * DateFormat dfm = new SimpleDateFormat("z"); - * dfm.setTimeZone(zone); boolean hasDaylight = - * zone.useDaylightTime(); String first = dfm.format(new Date(2010, - * 1, 1)); String second = dfm.format(new Date(2011, 6, 6)); int mid - * = hour * -1; String result = first + Integer.toString(mid); - * if(hasDaylight){ result = result + second; } - * timeZoneComboBox.addItem(item + " (" + result + ")"); - */ - timeZoneComboBox.addItem(item); - } - // get the current timezone - TimeZone thisTimeZone = Calendar.getInstance().getTimeZone(); - int thisOffset = thisTimeZone.getRawOffset() / 1000; - int thisHour = thisOffset / 3600; - int thisMinutes = (thisOffset % 3600) / 60; - String formatted = String.format("(GMT%+d:%02d) %s", thisHour, thisMinutes, thisTimeZone.getID()); - - // set the selected timezone - timeZoneComboBox.setSelectedItem(formatted); - } /** * This method is called from within the constructor to initialize the form. @@ -272,10 +201,6 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { buttonGroup1 = new javax.swing.ButtonGroup(); jLabel2 = new javax.swing.JLabel(); nextLabel = new javax.swing.JLabel(); - timeZoneLabel = new javax.swing.JLabel(); - timeZoneComboBox = new javax.swing.JComboBox(); - noFatOrphansCheckbox = new javax.swing.JCheckBox(); - descLabel = new javax.swing.JLabel(); inputPanel = new javax.swing.JPanel(); typeTabel = new javax.swing.JLabel(); typePanel = new javax.swing.JPanel(); @@ -288,15 +213,6 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { org.openide.awt.Mnemonics.setLocalizedText(nextLabel, org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.nextLabel.text")); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.timeZoneLabel.text")); // NOI18N - - timeZoneComboBox.setMaximumRowCount(30); - - org.openide.awt.Mnemonics.setLocalizedText(noFatOrphansCheckbox, org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.noFatOrphansCheckbox.text")); // NOI18N - noFatOrphansCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.noFatOrphansCheckbox.toolTipText")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(descLabel, org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.descLabel.text")); // NOI18N - inputPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder()); org.openide.awt.Mnemonics.setLocalizedText(typeTabel, org.openide.util.NbBundle.getMessage(AddImageWizardChooseDataSourceVisual.class, "AddImageWizardChooseDataSourceVisual.typeTabel.text")); // NOI18N @@ -312,7 +228,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { ); typePanelLayout.setVerticalGroup( typePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 77, Short.MAX_VALUE) + .addGap(0, 173, Short.MAX_VALUE) ); javax.swing.GroupLayout inputPanelLayout = new javax.swing.GroupLayout(inputPanel); @@ -338,7 +254,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { .addComponent(typeTabel) .addComponent(typeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(typePanel, javax.swing.GroupLayout.DEFAULT_SIZE, 77, Short.MAX_VALUE) + .addComponent(typePanel, javax.swing.GroupLayout.DEFAULT_SIZE, 173, Short.MAX_VALUE) .addContainerGap()) ); @@ -356,14 +272,6 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(nextLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGroup(layout.createSequentialGroup() - .addComponent(timeZoneLabel) - .addGap(18, 18, 18) - .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 252, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(noFatOrphansCheckbox) - .addGroup(layout.createSequentialGroup() - .addGap(21, 21, 21) - .addComponent(descLabel)) .addComponent(imgInfoLabel)) .addGap(0, 54, Short.MAX_VALUE))) .addContainerGap()) @@ -375,29 +283,17 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { .addComponent(imgInfoLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(inputPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(timeZoneLabel) - .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(noFatOrphansCheckbox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(descLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 64, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 45, Short.MAX_VALUE) .addComponent(nextLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, 0)) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.ButtonGroup buttonGroup1; - private javax.swing.JLabel descLabel; private javax.swing.JLabel imgInfoLabel; private javax.swing.JPanel inputPanel; private javax.swing.JLabel jLabel2; private javax.swing.JLabel nextLabel; - private javax.swing.JCheckBox noFatOrphansCheckbox; - private javax.swing.JComboBox timeZoneComboBox; - private javax.swing.JLabel timeZoneLabel; private javax.swing.JComboBox typeComboBox; private javax.swing.JPanel typePanel; private javax.swing.JLabel typeTabel; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java index 5a89aa2997..832f93d348 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java @@ -37,7 +37,6 @@ import javax.swing.event.ChangeListener; import org.openide.WizardDescriptor; import org.openide.util.HelpCtx; import org.openide.util.Lookup; -//import org.sleuthkit.autopsy.casemodule.ContentTypePanel.ContentType; import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.PlatformUtil; @@ -68,27 +67,21 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel newContents = Collections.synchronizedList(new ArrayList()); private boolean ingested = false; private boolean readyToIngest = false; - // the paths of the image files to be added - private String dataSourcePath; - private String dataSourceType; - // the time zone where the image is added - private String timeZone; - //whether to not process FAT filesystem orphans - private boolean noFatOrphans; + // task that will clean up the created database file if the wizard is cancelled before it finishes - private AddImageAction.CleanupTask cleanupImage; // initialized to null in readSettings() - private CurrentDirectoryFetcher fetcher; - private AddImageProcess process; + private AddImageAction.CleanupTask cleanupTask; + private AddImageAction addImageAction; - private AddImageTask addImageTask; - private AddLocalFilesTask addLocalFilesTask; + private AddImageWizardAddingProgressPanel progressPanel; private AddImageWizardChooseDataSourcePanel dataSourcePanel; + private DataSourceProcessor dsProcessor; - private AddImageAction.CleanupTask cleanupTask; + AddImageWizardIngestConfigPanel(AddImageWizardChooseDataSourcePanel dsPanel, AddImageAction action, AddImageWizardAddingProgressPanel proPanel) { this.addImageAction = action; @@ -188,27 +181,13 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel { - - AddImageTask task; - JProgressBar prog; - AddImageWizardAddingProgressVisual wiz; - AddImageProcess proc; - - CurrentDirectoryFetcher(JProgressBar prog, AddImageWizardAddingProgressVisual wiz, AddImageProcess proc) { - this.wiz = wiz; - this.proc = proc; - this.prog = prog; - } - - /** - * @return the currently processing directory - */ - @Override - protected Integer doInBackground() { - try { - while (prog.getValue() < 100 || prog.isIndeterminate()) { //TODO Rely on state variable in AddImgTask class - - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - wiz.setCurrentDirText(proc.currentDirectory()); - } - }); - - Thread.sleep(2 * 1000); - } - return 1; - } catch (InterruptedException ie) { - return -1; - } - } - } - - /** - * Thread that will add logical files to database, and then kick-off ingest - * modules. Note: the add logical files task cannot currently be reverted as - * the add image task can. This is a separate task from AddImgTask because - * it is much simpler and does not require locks, since the underlying file - * manager methods acquire the locks for each transaction when adding - * logical files. - */ - private class AddLocalFilesTask extends SwingWorker { - - private JProgressBar progressBar; - private Case currentCase; - // true if the process was requested to stop - private boolean interrupted = false; - private boolean hasCritError = false; - private String errorString = null; - private WizardDescriptor settings; - private Logger logger = Logger.getLogger(AddLocalFilesTask.class.getName()); - - protected AddLocalFilesTask(WizardDescriptor settings) { - this.progressBar = progressPanel.getComponent().getProgressBar(); - currentCase = Case.getCurrentCase(); - this.settings = settings; - } - - /** - * Starts the addImage process, but does not commit the results. - * - * @return - * - * @throws Exception - */ - @Override - protected Integer doInBackground() { - this.setProgress(0); - // Add a cleanup task to interupt the backgroud process if the - // wizard exits while the background process is running. - AddImageAction.CleanupTask cancelledWhileRunning = addImageAction.new CleanupTask() { - @Override - void cleanup() throws Exception { - logger.log(Level.INFO, "Add logical files process interrupted."); - //nothing to be cleanedup - } - }; - - cancelledWhileRunning.enable(); - final LocalFilesAddProgressUpdater progUpdater = new LocalFilesAddProgressUpdater(this.progressBar, progressPanel.getComponent()); - try { - final FileManager fileManager = currentCase.getServices().getFileManager(); - progressPanel.setStateStarted(); - String[] paths = dataSourcePath.split(LocalFilesPanel.FILES_SEP); - List absLocalPaths = new ArrayList(); - for (String path : paths) { - absLocalPaths.add(path); - } - newContents.add(fileManager.addLocalFilesDirs(absLocalPaths, progUpdater)); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Errors occurred while running add logical files. ", ex); - hasCritError = true; - errorString = ex.getMessage(); - } finally { - // process is over, doesn't need to be dealt with if cancel happens - cancelledWhileRunning.disable(); - //enqueue what would be in done() to EDT thread - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - postProcess(); - } - }); - } - return 0; - } - - /** - * - * (called by EventDispatch Thread after doInBackground finishes) - */ - protected void postProcess() { - progressBar.setIndeterminate(false); - setProgress(100); - - //clear updates - // progressPanel.getComponent().setProcessInvis(); - - if (interrupted || hasCritError) { - logger.log(Level.INFO, "Handling errors or interruption that occured in logical files process"); - if (hasCritError) { - //core error - progressPanel.getComponent().showErrors(errorString, true); - } - return; - } else { - if (errorString != null) { - //data error (non-critical) - logger.log(Level.INFO, "Handling non-critical errors that occured in logical files process"); - progressPanel.getComponent().showErrors(errorString, false); - } - } - try { - // When everything happens without an error: - if (errorString == null) { // complete progress bar - progressPanel.getComponent().setProgressBarTextAndColor("*Logical Files added.", 100, Color.black); - } - - // Get attention for the process finish - java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP! - AddImageWizardAddingProgressVisual panel = progressPanel.getComponent(); - if (panel != null) { - Window w = SwingUtilities.getWindowAncestor(panel); - if (w != null) { - w.toFront(); - } - } - - progressPanel.setStateFinished(); - - //notify the case - if (!newContents.isEmpty()) { - Case.getCurrentCase().addLocalDataSource(newContents.get(0)); - } - - // Start ingest if we can - startIngest(); - - } catch (Exception ex) { - //handle unchecked exceptions - logger.log(Level.WARNING, "Unexpected errors occurred while running post add image cleanup. ", ex); - progressPanel.getComponent().setProgressBarTextAndColor("*Failed to add image.", 0, Color.black); // set error message - logger.log(Level.SEVERE, "Error adding image to case", ex); - } - } - - /** - * Updates the wizard status with logical file/folder - */ - private class LocalFilesAddProgressUpdater implements FileManager.FileAddProgressUpdater { - - private int count = 0; - private JProgressBar prog; - private AddImageWizardAddingProgressVisual wiz; - - LocalFilesAddProgressUpdater(JProgressBar prog, AddImageWizardAddingProgressVisual wiz) { - this.wiz = wiz; - this.prog = prog; - } - - @Override - public void fileAdded(final AbstractFile newFile) { - if (count++ % 10 == 0 && (prog.getValue() < 100 || prog.isIndeterminate())) { - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - wiz.setCurrentDirText(newFile.getParentPath() + "/" + newFile.getName()); - } - }); - - } - } - } - } - - /** - * Thread that will make the JNI call to add image to database, and then - * kick-off ingest modules. - */ - private class AddImageTask extends SwingWorker { - - private JProgressBar progressBar; - private Case currentCase; - // true if the process was requested to stop - private boolean interrupted = false; - private boolean hasCritError = false; - private String errorString = null; - private WizardDescriptor wizDescriptor; - private Logger logger = Logger.getLogger(AddImageTask.class.getName()); - - protected AddImageTask(WizardDescriptor settings) { - this.progressBar = progressPanel.getComponent().getProgressBar(); - currentCase = Case.getCurrentCase(); - this.wizDescriptor = settings; - } - - /** - * Starts the addImage process, but does not commit the results. - * - * @return - * - * @throws Exception - */ - @Override - protected Integer doInBackground() { - - this.setProgress(0); - - - // Add a cleanup task to interupt the backgroud process if the - // wizard exits while the background process is running. - AddImageAction.CleanupTask cancelledWhileRunning = addImageAction.new CleanupTask() { - @Override - void cleanup() throws Exception { - logger.log(Level.INFO, "Add image process interrupted."); - addImageTask.interrupt(); //it might take time to truly interrupt - } - }; - - - 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; - } - - process = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans); - fetcher = new CurrentDirectoryFetcher(this.progressBar, progressPanel.getComponent(), process); - cancelledWhileRunning.enable(); - try { - progressPanel.setStateStarted(); - fetcher.execute(); - process.run(new String[]{dataSourcePath}); - } 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; - errorString = ex.getMessage(); - } catch (TskDataException ex) { - logger.log(Level.WARNING, "Data errors occurred while running add image. ", ex); - errorString = ex.getMessage(); - } finally { - // process is over, doesn't need to be dealt with if cancel happens - cancelledWhileRunning.disable(); - - } - - 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(WizardDescriptor settings) throws Exception { - - String contentPath = (String) settings.getProperty(AddImageAction.DATASOURCEPATH_PROP); - - String timezone = settings.getProperty(AddImageAction.TIMEZONE_PROP).toString(); - settings.putProperty(AddImageAction.IMAGEID_PROP, ""); - - long imageId = 0; - try { - imageId = process.commit(); - } catch (TskException e) { - logger.log(Level.WARNING, "Errors occured while committing the image", e); - } finally { - //commit done, unlock db write in EWT thread - //before doing anything else - SleuthkitCase.dbWriteUnlock(); - - if (imageId != 0) { - Image newImage = Case.getCurrentCase().addImage(contentPath, 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) - progressPanel.addErrors(verificationErrors, false); - } - - - newContents.add(newImage); - settings.putProperty(AddImageAction.IMAGEID_PROP, imageId); - } - - // Can't bail and revert image add after commit, so disable image cleanup - // task - cleanupImage.disable(); - settings.putProperty(AddImageAction.IMAGECLEANUPTASK_PROP, null); - - logger.log(Level.INFO, "Image committed, imageId: " + imageId); - logger.log(Level.INFO, PlatformUtil.getAllMemUsageInfo()); - - } - } - - /** - * - * (called by EventDispatch Thread after doInBackground finishes) - */ - @Override - protected void done() { - //these are required to stop the CurrentDirectoryFetcher - progressBar.setIndeterminate(false); - setProgress(100); - - // attempt actions that might fail and force the process to stop - - if (interrupted || hasCritError) { - logger.log(Level.INFO, "Handling errors or interruption that occured in add image process"); - revert(); - if (hasCritError) { - //core error - progressPanel.addErrors(errorString, true); - } - return; - } - if (errorString != null) { - //data error (non-critical) - logger.log(Level.INFO, "Handling non-critical errors that occured in add image process"); - progressPanel.addErrors(errorString, false); - } - - - try { - // When everything happens without an error: - - // the add-image process needs to be reverted if the wizard doesn't finish - cleanupImage = addImageAction.new CleanupTask() { - //note, CleanupTask runs inside EWT thread - @Override - void cleanup() throws Exception { - logger.log(Level.INFO, "Running cleanup task after add image process"); - revert(); - } - }; - cleanupImage.enable(); - - if (errorString == null) { // complete progress bar - progressPanel.getComponent().setProgressBarTextAndColor("*Data Source added.", 100, Color.black); - } - - // Get attention for the process finish - java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP! - AddImageWizardAddingProgressVisual panel = progressPanel.getComponent(); - if (panel != null) { - Window w = SwingUtilities.getWindowAncestor(panel); - if (w != null) { - w.toFront(); - } - } - - // Tell the panel we're done - progressPanel.setStateFinished(); - - // Commit the image - if (!newContents.isEmpty()) //already commited - { - logger.log(Level.INFO, "Assuming image already committed, will not commit."); - return; - } - - if (process != null) { // and if we're done configuring ingest - // commit anything - try { - commitImage(wizDescriptor); - } catch (Exception ex) { - // Log error/display warning - logger.log(Level.SEVERE, "Error adding image to case.", ex); - } - } else { - logger.log(Level.SEVERE, "Missing image process object"); - } - - - - - // Start ingest if we can - startIngest(); - - } catch (Exception ex) { - //handle unchecked exceptions post image add - - logger.log(Level.WARNING, "Unexpected errors occurred while running post add image cleanup. ", ex); - - progressPanel.getComponent().setProgressBarTextAndColor("*Failed to add image.", 0, Color.black); // set error message - - // Log error/display warning - - logger.log(Level.SEVERE, "Error adding image to case", ex); - } finally { - } - } - - void interrupt() throws Exception { - interrupted = true; - try { - logger.log(Level.INFO, "interrupt() add image process"); - process.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); - } - } - - //runs in EWT - void revert() { - try { - logger.log(Level.INFO, "Revert after add image process"); - try { - process.revert(); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Error reverting add image process", ex); - } - } finally { - //unlock db write within EWT thread - SleuthkitCase.dbWriteUnlock(); - } - } - } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index ffb3261dd5..6207163194 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -134,12 +134,8 @@ LocalFilesPanel.selectButton.actionCommand=Add AddImageWizardIngestConfigVisual.subtitleLabel.text=Configure the ingest modules you would like to run on this data source. AddImageWizardIngestConfigVisual.titleLabel.text=Configure Ingest Modules AddImageWizardAddingProgressVisual.statusLabel.text=File system has been added to the local database. Files are being analyzed. -AddImageWizardChooseDataSourceVisual.noFatOrphansCheckbox.toolTipText= -AddImageWizardChooseDataSourceVisual.noFatOrphansCheckbox.text=Ignore orphan files in FAT file systems -AddImageWizardChooseDataSourceVisual.descLabel.text=(faster results, although some data will not be searched) AddImageWizardChooseDataSourceVisual.typeTabel.text=Select source type to add: AddImageWizardChooseDataSourceVisual.jLabel2.text=jLabel2 -AddImageWizardChooseDataSourceVisual.timeZoneLabel.text=Please select the input timezone: AddImageWizardChooseDataSourceVisual.nextLabel.text= Press 'Next' to analyze the input data, extract volume and file system data, and populate a local database. AddImageWizardChooseDataSourceVisual.imgInfoLabel.text=Enter Data Source Information: AddImageWizardAddingProgressVisual.progressLabel.text= @@ -148,3 +144,7 @@ AddImageWizardAddingProgressVisual.viewLogButton.text=View Log AddImageWizardAddingProgressVisual.titleLabel.text=Adding Data Source AddImageWizardAddingProgressVisual.subTitle1Label.text=File system information is being added to a local database. File analysis will start when this finishes. AddImageWizardAddingProgressVisual.subTitle2Label.text=Processing Data Source and Adding to Database +ImageFilePanel.timeZoneLabel.text=Please select the input timezone: +ImageFilePanel.noFatOrphansCheckbox.text=Ignore orphan files in FAT file systems +ImageFilePanel.noFatOrphansCheckbox.toolTipText= +ImageFilePanel.descLabel.text=(faster results, although some data will not be searched) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/DataSourceProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/DataSourceProcessor.java index 76f9b89f4e..b934809dea 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/DataSourceProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/DataSourceProcessor.java @@ -58,7 +58,7 @@ public interface DataSourceProcessor { * @param progressPanel progress panel to be updated while processing * **/ - void run(WizardDescriptor settings, DSPProgressMonitor progressPanel, DSPCallback dspCallback); + void run(DSPProgressMonitor progressPanel, DSPCallback dspCallback); /** * Called after run() is done to get the new content added by the handler. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java index 696f903f4e..eed578d9b0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java @@ -61,13 +61,6 @@ public class ImageDSProcessor implements DataSourceProcessor { } - /**** - @Override - public ImageDSProcessor createInstance() { - return new ImageDSProcessor(); - } - *****/ - @Override public String getType() { @@ -84,8 +77,10 @@ public class ImageDSProcessor implements DataSourceProcessor { logger.log(Level.INFO, "RAMAN getPanel()..."); - // RAMAN TBD: we should preload the panel with any saved settings + // RAMAN TBD: we should ask the panel to preload with any saved settings + imageFilePanel.select(); + return imageFilePanel; } @@ -101,7 +96,7 @@ public class ImageDSProcessor implements DataSourceProcessor { } @Override - public void run(WizardDescriptor settings, DSPProgressMonitor progressMonitor, DSPCallback cbObj) { + public void run(DSPProgressMonitor progressMonitor, DSPCallback cbObj) { logger.log(Level.INFO, "RAMAN run()..."); @@ -112,38 +107,20 @@ public class ImageDSProcessor implements DataSourceProcessor { { // get the image options from the panel imagePath = imageFilePanel.getContentPaths(); - - /*** RAMAN TBD: get the TZ and NoFatOrhpns options from the config panel ******/ - //timeZone = imageFilePanel.getTimeZone(); - //noFatOrphans = imageFilePanel.getNoFatOrphans(); - - - + timeZone = imageFilePanel.getTimeZone(); + noFatOrphans = imageFilePanel.getNoFatOrphans(); } - addImageTask = new AddImageTask(settings, progressMonitor, cbObj); - - /**** RAMAN TBD: set other params needed by AddImageTask - such as TZ and NoFatOrhpans **/ - addImageTask.SetImageOptions(imagePath); - - + addImageTask = new AddImageTask(progressMonitor, cbObj); + // set the image options needed by AddImageTask - such as TZ and NoFatOrphans **/ + addImageTask.SetImageOptions(imagePath, timeZone, noFatOrphans); + addImageTask.execute(); return; } - /*** - @Override - public String[] getErrors() { - - logger.log(Level.INFO, "RAMAN getErrors()..."); - - // RAMAN TBD - return null; - } - *****/ - @Override public void cancel() { @@ -155,12 +132,6 @@ public class ImageDSProcessor implements DataSourceProcessor { return; } - /***** - @Override - public List getNewContents() { - return addImageTask.getNewContents(); - } - * *****/ @Override public void reset() { @@ -192,6 +163,8 @@ public class ImageDSProcessor implements DataSourceProcessor { 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; @@ -202,9 +175,6 @@ public class ImageDSProcessor implements DataSourceProcessor { private List errorList = new ArrayList(); - private WizardDescriptor wizDescriptor; - - private Logger logger = Logger.getLogger(AddImageTask.class.getName()); private DSPProgressMonitor progressMonitor; private DSPCallback callbackObj; @@ -220,12 +190,10 @@ public class ImageDSProcessor implements DataSourceProcessor { - public void SetImageOptions(String imgPath) { + public void SetImageOptions(String imgPath, String tz, boolean noOrphans) { this.imagePath = imgPath; - - // RAMAN TBD: also set TZ and noFatOrphans - // this.timeZone = tz; - // this.noFatOrphans = noFatOrphans; + this.timeZone = tz; + this.noFatOrphans = noOrphans; } @@ -264,12 +232,11 @@ public class ImageDSProcessor implements DataSourceProcessor { } - protected AddImageTask(WizardDescriptor settings, DSPProgressMonitor aProgressMonitor, DSPCallback cbObj ) { + protected AddImageTask(DSPProgressMonitor aProgressMonitor, DSPCallback cbObj ) { this.progressMonitor = aProgressMonitor; currentCase = Case.getCurrentCase(); this.callbackObj = cbObj; - this.wizDescriptor = settings; } /** @@ -307,19 +274,6 @@ public class ImageDSProcessor implements DataSourceProcessor { logger.log(Level.WARNING, "Errors occurred while running add image, could not acquire lock. ", ex); return 0; } - - - - - - /*** RAMAN TBD: TZ and NoFatOrpjhans should be moved into the Image panel and then should be set by the DSP - * instead of the settings. - * - */ - timeZone = wizDescriptor.getProperty(AddImageAction.TIMEZONE_PROP).toString(); - noFatOrphans = ((Boolean) wizDescriptor.getProperty(AddImageAction.NOFATORPHANS_PROP)).booleanValue(); - - addImageProcess = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans); fetcher = new CurrentDirectoryFetcher(progressMonitor, addImageProcess); @@ -355,14 +309,9 @@ public class ImageDSProcessor implements DataSourceProcessor { * * @throws Exception if commit or adding the image to the case failed */ - private void commitImage(WizardDescriptor settings) throws Exception { + private void commitImage() throws Exception { logger.log(Level.INFO, "RAMAN: commitImage()..."); - - String contentPath = (String) settings.getProperty(AddImageAction.DATASOURCEPATH_PROP); - - String timezone = settings.getProperty(AddImageAction.TIMEZONE_PROP).toString(); - settings.putProperty(AddImageAction.IMAGEID_PROP, ""); long imageId = 0; try { @@ -376,7 +325,7 @@ public class ImageDSProcessor implements DataSourceProcessor { SleuthkitCase.dbWriteUnlock(); if (imageId != 0) { - Image newImage = Case.getCurrentCase().addImage(contentPath, imageId, timezone); + Image newImage = Case.getCurrentCase().addImage(imagePath, imageId, timeZone); //while we have the image, verify the size of its contents String verificationErrors = newImage.verifyImageSize(); @@ -385,23 +334,13 @@ public class ImageDSProcessor implements DataSourceProcessor { errorList.add(verificationErrors); } - // + // Add the image to the list of new content newContents.add(newImage); - - // RAMAN TBD: imageID should be return via the callback - settings.putProperty(AddImageAction.IMAGEID_PROP, imageId); + } - // Can't bail and revert image add after commit, so disable image cleanup - // task - - - - settings.putProperty(AddImageAction.IMAGECLEANUPTASK_PROP, null); - logger.log(Level.INFO, "Image committed, imageId: " + imageId); logger.log(Level.INFO, PlatformUtil.getAllMemUsageInfo()); - } } @@ -424,7 +363,6 @@ public class ImageDSProcessor implements DataSourceProcessor { 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(); @@ -469,7 +407,7 @@ public class ImageDSProcessor implements DataSourceProcessor { if (addImageProcess != null) { // and if we're done configuring ingest // commit anything try { - commitImage(wizDescriptor); + commitImage(); } catch (Exception ex) { errorList.add(ex.getMessage()); // Log error/display warning diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form index 313ae952b8..39566f7376 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form @@ -31,8 +31,20 @@ - - + + + + + + + + + + + + + + @@ -45,6 +57,16 @@ + + + + + + + + + + @@ -74,5 +96,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java index 275c3dced8..e7aaa3e987 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java @@ -22,7 +22,10 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.File; import java.util.ArrayList; +import java.util.Calendar; import java.util.List; +import java.util.SimpleTimeZone; +import java.util.TimeZone; import javax.swing.JFileChooser; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; @@ -47,6 +50,10 @@ public class ImageFilePanel extends JPanel implements DocumentListener { fc.addChoosableFileFilter(AddImageWizardChooseDataSourceVisual.rawFilter); fc.addChoosableFileFilter(AddImageWizardChooseDataSourceVisual.encaseFilter); fc.setFileFilter(AddImageWizardChooseDataSourceVisual.allFilter); + + createTimeZoneList(); + noFatOrphansCheckbox.setEnabled(true); + } /** @@ -80,6 +87,10 @@ public class ImageFilePanel extends JPanel implements DocumentListener { pathLabel = new javax.swing.JLabel(); browseButton = new javax.swing.JButton(); pathTextField = new javax.swing.JTextField(); + timeZoneLabel = new javax.swing.JLabel(); + timeZoneComboBox = new javax.swing.JComboBox(); + noFatOrphansCheckbox = new javax.swing.JCheckBox(); + descLabel = new javax.swing.JLabel(); setMinimumSize(new java.awt.Dimension(0, 65)); setPreferredSize(new java.awt.Dimension(403, 65)); @@ -95,6 +106,15 @@ public class ImageFilePanel extends JPanel implements DocumentListener { pathTextField.setText(org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.pathTextField.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.timeZoneLabel.text")); // NOI18N + + timeZoneComboBox.setMaximumRowCount(30); + + org.openide.awt.Mnemonics.setLocalizedText(noFatOrphansCheckbox, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.noFatOrphansCheckbox.text")); // NOI18N + noFatOrphansCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.noFatOrphansCheckbox.toolTipText")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(descLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.descLabel.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -105,8 +125,17 @@ public class ImageFilePanel extends JPanel implements DocumentListener { .addComponent(browseButton) .addGap(2, 2, 2)) .addGroup(layout.createSequentialGroup() - .addComponent(pathLabel) - .addGap(0, 284, Short.MAX_VALUE)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(timeZoneLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(pathLabel) + .addComponent(noFatOrphansCheckbox) + .addGroup(layout.createSequentialGroup() + .addGap(21, 21, 21) + .addComponent(descLabel))) + .addGap(0, 20, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -115,7 +144,16 @@ public class ImageFilePanel extends JPanel implements DocumentListener { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(browseButton) - .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(timeZoneLabel) + .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(noFatOrphansCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(descLabel) + .addContainerGap(19, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -137,8 +175,12 @@ public class ImageFilePanel extends JPanel implements DocumentListener { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton browseButton; + private javax.swing.JLabel descLabel; + private javax.swing.JCheckBox noFatOrphansCheckbox; private javax.swing.JLabel pathLabel; private javax.swing.JTextField pathTextField; + private javax.swing.JComboBox timeZoneComboBox; + private javax.swing.JLabel timeZoneLabel; // End of variables declaration//GEN-END:variables /** @@ -156,6 +198,16 @@ public class ImageFilePanel extends JPanel implements DocumentListener { pathTextField.setText(s); } + public String getTimeZone() { + String tz = timeZoneComboBox.getSelectedItem().toString(); + return tz.substring(tz.indexOf(")") + 2).trim(); + + } + + boolean getNoFatOrphans() { + return noFatOrphansCheckbox.isSelected(); + } + public String getContentType() { return "IMAGE"; } @@ -173,6 +225,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener { if (path == null || path.isEmpty()) { return false; } + boolean isExist = Case.pathExists(path); boolean isPhysicalDrive = Case.isPhysicalDrive(path); boolean isPartition = Case.isPartition(path); @@ -180,6 +233,42 @@ public class ImageFilePanel extends JPanel implements DocumentListener { return (isExist || isPhysicalDrive || isPartition); } + + /** + * Creates the drop down list for the time zones and then makes the local + * machine time zone to be selected. + */ + public void createTimeZoneList() { + // load and add all timezone + String[] ids = SimpleTimeZone.getAvailableIDs(); + for (String id : ids) { + TimeZone zone = TimeZone.getTimeZone(id); + int offset = zone.getRawOffset() / 1000; + int hour = offset / 3600; + int minutes = (offset % 3600) / 60; + String item = String.format("(GMT%+d:%02d) %s", hour, minutes, id); + + /* + * DateFormat dfm = new SimpleDateFormat("z"); + * dfm.setTimeZone(zone); boolean hasDaylight = + * zone.useDaylightTime(); String first = dfm.format(new Date(2010, + * 1, 1)); String second = dfm.format(new Date(2011, 6, 6)); int mid + * = hour * -1; String result = first + Integer.toString(mid); + * if(hasDaylight){ result = result + second; } + * timeZoneComboBox.addItem(item + " (" + result + ")"); + */ + timeZoneComboBox.addItem(item); + } + // get the current timezone + TimeZone thisTimeZone = Calendar.getInstance().getTimeZone(); + int thisOffset = thisTimeZone.getRawOffset() / 1000; + int thisHour = thisOffset / 3600; + int thisMinutes = (thisOffset % 3600) / 60; + String formatted = String.format("(GMT%+d:%02d) %s", thisHour, thisMinutes, thisTimeZone.getID()); + + // set the selected timezone + timeZoneComboBox.setSelectedItem(formatted); + } /** * Update functions are called by the pathTextField which has this set * as it's DocumentEventListener. Each update function fires a property change diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index 4744f62146..357d499b2f 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Wed, 25 Sep 2013 13:55:37 -0400 +#Thu, 17 Oct 2013 13:25:49 -0400 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=288 SPLASH_WIDTH=538 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 0dbd5e9a00..913a689dc0 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Wed, 25 Sep 2013 13:55:37 -0400 +#Thu, 17 Oct 2013 13:25:49 -0400 CTL_MainWindow_Title=Autopsy 3.0.7 CTL_MainWindow_Title_No_Project=Autopsy 3.0.7 From 26fcd4b49ed1fc5ab93e341dbd05282d823a7a22 Mon Sep 17 00:00:00 2001 From: raman-bt Date: Thu, 17 Oct 2013 15:35:26 -0400 Subject: [PATCH 06/21] Sundry cleanup. --- .../AddImageWizardChooseDataSourceVisual.java | 17 ++------- .../AddImageWizardIngestConfigPanel.java | 11 ++++++ .../autopsy/casemodule/ImageDSProcessor.java | 20 +--------- .../autopsy/casemodule/ImageFilePanel.form | 4 +- .../autopsy/casemodule/ImageFilePanel.java | 37 +++++++++++++++---- 5 files changed, 46 insertions(+), 43 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java index 96440ffd3f..ab9746b62c 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java @@ -53,20 +53,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { UPDATE_UI, FOCUS_NEXT }; - static final List rawExt = Arrays.asList(new String[]{".img", ".dd", ".001", ".aa", ".raw"}); - static final String rawDesc = "Raw Images (*.img, *.dd, *.001, *.aa, *.raw)"; - static GeneralFilter rawFilter = new GeneralFilter(rawExt, rawDesc); - static final List encaseExt = Arrays.asList(new String[]{".e01"}); - static final String encaseDesc = "Encase Images (*.e01)"; - static GeneralFilter encaseFilter = new GeneralFilter(encaseExt, encaseDesc); - static final List allExt = new ArrayList(); - - static { - allExt.addAll(rawExt); - allExt.addAll(encaseExt); - } - static final String allDesc = "All Supported Types"; - static GeneralFilter allFilter = new GeneralFilter(allExt, allDesc); + private AddImageWizardChooseDataSourcePanel wizPanel; private JPanel currentPanel; @@ -123,6 +110,8 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { if (!datasourceProcessorsMap.containsKey(dsProcessor.getType()) ) { if (!datasourceProcessorsMap.containsKey(dsProcessor.getType()) ) { + + dsProcessor.reset(); datasourceProcessorsMap.put(dsProcessor.getType(), dsProcessor); } else { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java index 832f93d348..4c5b879aa6 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java @@ -273,6 +273,17 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel - + - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java index e7aaa3e987..04a9d78767 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java @@ -22,6 +22,7 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.List; import java.util.SimpleTimeZone; @@ -35,6 +36,24 @@ import javax.swing.JPanel; * ImageTypePanel for adding an image file such as .img, .E0x, .00x, etc. */ public class ImageFilePanel extends JPanel implements DocumentListener { + + static final List rawExt = Arrays.asList(new String[]{".img", ".dd", ".001", ".aa", ".raw"}); + static final String rawDesc = "Raw Images (*.img, *.dd, *.001, *.aa, *.raw)"; + static GeneralFilter rawFilter = new GeneralFilter(rawExt, rawDesc); + static final List encaseExt = Arrays.asList(new String[]{".e01"}); + static final String encaseDesc = "Encase Images (*.e01)"; + static GeneralFilter encaseFilter = new GeneralFilter(encaseExt, encaseDesc); + static final List allExt = new ArrayList(); + + static { + allExt.addAll(rawExt); + allExt.addAll(encaseExt); + } + static final String allDesc = "All Supported Types"; + static GeneralFilter allFilter = new GeneralFilter(allExt, allDesc); + + + private static ImageFilePanel instance = null; private PropertyChangeSupport pcs = null; private JFileChooser fc = new JFileChooser(); @@ -47,13 +66,11 @@ public class ImageFilePanel extends JPanel implements DocumentListener { fc.setDragEnabled(false); fc.setFileSelectionMode(JFileChooser.FILES_ONLY); fc.setMultiSelectionEnabled(false); - fc.addChoosableFileFilter(AddImageWizardChooseDataSourceVisual.rawFilter); - fc.addChoosableFileFilter(AddImageWizardChooseDataSourceVisual.encaseFilter); - fc.setFileFilter(AddImageWizardChooseDataSourceVisual.allFilter); + fc.addChoosableFileFilter(rawFilter); + fc.addChoosableFileFilter(encaseFilter); + fc.setFileFilter(allFilter); createTimeZoneList(); - noFatOrphansCheckbox.setEnabled(true); - } /** @@ -148,12 +165,12 @@ public class ImageFilePanel extends JPanel implements DocumentListener { .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(timeZoneLabel) - .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(noFatOrphansCheckbox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(descLabel) - .addContainerGap(19, Short.MAX_VALUE)) + .addContainerGap(13, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -213,7 +230,11 @@ public class ImageFilePanel extends JPanel implements DocumentListener { } public void reset() { - //nothing to reset + //reset the UI elements to default + + pathTextField.setText(null); + + } /** From f67cd305fcf95fb31c150d6ff4a1e26bbe2812fe Mon Sep 17 00:00:00 2001 From: raman-bt Date: Fri, 18 Oct 2013 08:54:40 -0400 Subject: [PATCH 07/21] Move all interfaces to corecomponentinterfaces package. --- .../casemodule/AddImageWizardAddingProgressPanel.java | 2 ++ .../casemodule/AddImageWizardChooseDataSourceVisual.java | 2 ++ .../autopsy/casemodule/AddImageWizardIngestConfigPanel.java | 6 ++++-- .../org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java | 4 ++++ .../DSPCallback.java | 6 +++--- .../DSPProgressMonitor.java | 2 +- .../DataSourceProcessor.java | 3 +-- 7 files changed, 17 insertions(+), 8 deletions(-) rename Core/src/org/sleuthkit/autopsy/{casemodule => corecomponentinterfaces}/DSPCallback.java (78%) rename Core/src/org/sleuthkit/autopsy/{casemodule => corecomponentinterfaces}/DSPProgressMonitor.java (89%) rename Core/src/org/sleuthkit/autopsy/{casemodule => corecomponentinterfaces}/DataSourceProcessor.java (95%) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java index 3817565c54..46592d269e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.casemodule; + import java.awt.Color; import java.util.HashSet; import java.util.Iterator; @@ -27,6 +28,7 @@ import javax.swing.event.ChangeListener; import org.openide.WizardDescriptor; import org.openide.util.HelpCtx; import org.openide.util.Lookup; +import org.sleuthkit.autopsy.corecomponentinterfaces.DSPProgressMonitor; /** * The final panel of the add image wizard. It displays a progress bar and diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java index ab9746b62c..12fdeceb1f 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.casemodule; + import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -39,6 +40,7 @@ import javax.swing.event.DocumentEvent; import javax.swing.event.ListDataListener; import org.openide.util.Lookup; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; /** * visual component for the first panel of add image wizard. Allows user to pick diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java index 4c5b879aa6..df965f7ea0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.casemodule; + import org.sleuthkit.autopsy.ingest.IngestConfigurator; import java.awt.Color; import java.awt.Component; @@ -51,7 +52,8 @@ import org.sleuthkit.datamodel.TskDataException; import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.Volume; import org.sleuthkit.datamodel.VolumeSystem; - +import org.sleuthkit.autopsy.corecomponentinterfaces.DSPCallback; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; /** * second panel of add image wizard, allows user to configure ingest modules. * @@ -249,7 +251,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel errList, List contents) { + public void doneEDT(DSPCallback.DSP_Result result, List errList, List contents) { dataSourceProcessorDone(result, errList, contents ); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java index 5e5b077b6b..dc0c1bf4b2 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java @@ -4,6 +4,7 @@ */ package org.sleuthkit.autopsy.casemodule; + import java.awt.Color; import java.awt.EventQueue; import java.awt.Window; @@ -28,6 +29,9 @@ import org.sleuthkit.datamodel.SleuthkitJNI; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskDataException; import org.sleuthkit.datamodel.TskException; +import org.sleuthkit.autopsy.corecomponentinterfaces.DSPProgressMonitor; +import org.sleuthkit.autopsy.corecomponentinterfaces.DSPCallback; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; /** * diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/DSPCallback.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPCallback.java similarity index 78% rename from Core/src/org/sleuthkit/autopsy/casemodule/DSPCallback.java rename to Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPCallback.java index 58ec4d8ce0..553cb71ebe 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/DSPCallback.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPCallback.java @@ -2,7 +2,7 @@ * To change this template, choose Tools | Templates * and open the template in the editor. */ -package org.sleuthkit.autopsy.casemodule; +package org.sleuthkit.autopsy.corecomponentinterfaces; import java.awt.EventQueue; import java.util.List; @@ -21,7 +21,7 @@ public abstract class DSPCallback { NONCRITICAL_ERRORS, }; - void done(DSP_Result result, List errList, List newContents) + public void done(DSP_Result result, List errList, List newContents) { final DSP_Result resultf = result; @@ -38,5 +38,5 @@ public abstract class DSPCallback { }); } - abstract void doneEDT(DSP_Result result, List errList, List newContents); + public abstract void doneEDT(DSP_Result result, List errList, List newContents); }; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/DSPProgressMonitor.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPProgressMonitor.java similarity index 89% rename from Core/src/org/sleuthkit/autopsy/casemodule/DSPProgressMonitor.java rename to Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPProgressMonitor.java index d3acea384c..b375301aed 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/DSPProgressMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPProgressMonitor.java @@ -2,7 +2,7 @@ * To change this template, choose Tools | Templates * and open the template in the editor. */ -package org.sleuthkit.autopsy.casemodule; +package org.sleuthkit.autopsy.corecomponentinterfaces; /* * An GUI agnostic DSPProgressMonitor interface for DataSorceProcesssors to diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/DataSourceProcessor.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessor.java similarity index 95% rename from Core/src/org/sleuthkit/autopsy/casemodule/DataSourceProcessor.java rename to Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessor.java index b934809dea..59fc291c6e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/DataSourceProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessor.java @@ -16,12 +16,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.casemodule; +package org.sleuthkit.autopsy.corecomponentinterfaces; import java.util.List; import javax.swing.JPanel; import org.openide.WizardDescriptor; -import org.sleuthkit.autopsy.casemodule.DSPProgressMonitor; import org.sleuthkit.datamodel.Content; public interface DataSourceProcessor { From aa01261c9a50ad31ff374e55fb8cb6b562e590d6 Mon Sep 17 00:00:00 2001 From: raman-bt Date: Fri, 18 Oct 2013 10:11:47 -0400 Subject: [PATCH 08/21] Cleanup comments, logging, javadocs etc. --- .../AddImageWizardChooseDataSourcePanel.java | 11 +- .../AddImageWizardChooseDataSourceVisual.java | 6 +- .../AddImageWizardIngestConfigPanel.java | 31 ++-- .../autopsy/casemodule/ContentTypePanel.java | 96 ----------- .../autopsy/casemodule/ImageDSProcessor.java | 156 ++++++++++-------- .../corecomponentinterfaces/DSPCallback.java | 9 +- 6 files changed, 115 insertions(+), 194 deletions(-) delete mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/ContentTypePanel.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java index 777b402eb3..1588d865b5 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java @@ -180,10 +180,11 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel errList, List contents) { @@ -264,18 +261,22 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel errList, List contents) { - logger.log(Level.INFO, "RAMAN dataSourceProcessorDone()."); // disable the cleanup task cleanupTask.disable(); - // Get attention for the process finish java.awt.Toolkit.getDefaultToolkit().beep(); //BEEP! AddImageWizardAddingProgressVisual panel = progressPanel.getComponent(); @@ -295,8 +296,8 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.casemodule; - -import java.beans.PropertyChangeListener; -import javax.swing.JPanel; -import java.util.ArrayList; -import java.util.List; - -/************ -abstract class ContentTypePanel extends JPanel { - - // Collection of panels that are dynamically discovered and registered - private static List registeredPanels = new ArrayList();; - - public static void RegisterPanel(ContentTypePanel panel) - { - // RAMAN TBD: check if this panel is already regsitered... - - registeredPanels.add(panel); - - - } - //public enum ContentType{IMAGE, DISK, LOCAL}; - - - private String contentType; - -// -// * Returns a list off all the panels extending ImageTypePanel. -// * @return list of all ImageTypePanels -// - public static ContentTypePanel[] getPanels() { - //return new ContentTypePanel[] {ImageFilePanel.getDefault(), LocalDiskPanel.getDefault(), LocalFilesPanel.getDefault() }; - - - - - - return registeredPanels.toArray(new ContentTypePanel[registeredPanels.size()]); - } - -// -// * Return the path of the selected content in this panel. -// * @return paths to selected content (one or more if multiselect supported) -// - abstract public String getContentPaths(); - -// -// * Set the selected content in this panel to the provided path. -// * This function is optional. -// * @param s path to selected content -// - abstract public void setContentPath(String s); - -// -// * Get content type (image, disk, local file) of the source this wizard panel is for -// * @return ContentType of the source panel -// - abstract public String getContentType(); - -// -// * Returns if the next button should be enabled in the current wizard. -// * @return true if the next button should be enabled, false otherwise -// - abstract public boolean enableNext(); - -// -// * Tells this panel to reset itself -// - abstract public void reset(); - -// -// * Tells this panel it has been selected. -// - abstract public void select(); - - -} -***************/ \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java index dc0c1bf4b2..89098c8f46 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java @@ -34,81 +34,101 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DSPCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; /** - * - * @author raman + * Image data source processor. + * Handles the addition of "disk images" to Autopsy. + * + * An instance of this class is created via the Netbeans Lookup() method. + * */ @ServiceProvider(service = DataSourceProcessor.class) public class ImageDSProcessor implements DataSourceProcessor { static final Logger logger = Logger.getLogger(ImageDSProcessor.class.getName()); + // The Config UI panel that plugins into the Choose Data Source Wizard private ImageFilePanel imageFilePanel; + + // The Background task that does the actual work of adding the image private AddImageTask addImageTask; + // true of cancelled by the caller private boolean cancelled = false; DSPCallback callbackObj = null; // set to TRUE if the image options have been set via API and config Jpanel should be ignored private boolean imageOptionsSet = false; + + // image options private String imagePath; private String timeZone; private boolean noFatOrphans; - + /* + * A no argument constructor is required for the NM lookup() method to create an object + */ public ImageDSProcessor() { - logger.log(Level.INFO, "RAMAN ImageDSProcessor()..."); // Create the config panel imageFilePanel = ImageFilePanel.getDefault(); } - + /** + * Returns the Data source type (string) handled by this DSP + * + * @return String the data source type + **/ @Override public String getType() { - - logger.log(Level.INFO, "RAMAN getName()..."); - return imageFilePanel.getContentType(); - } - + /** + * Returns the JPanel for collecting the Data source information + * + * @return JPanel the config panel + **/ @Override public JPanel getPanel() { - - logger.log(Level.INFO, "RAMAN getPanel()..."); - + // RAMAN TBD: we should ask the panel to preload with any saved settings imageFilePanel.select(); return imageFilePanel; } - + /** + * Validates the data collected by the JPanel + * + * @return String returns NULL if success, error string if there is any errors + **/ @Override public String validatePanel() { - logger.log(Level.INFO, "RAMAN validatePanel()..."); - if (imageFilePanel.validatePanel() ) return null; else return "Error in panel"; } - + /** + * Runs the data source processor. + * This must kick off processing the data source in background + * + * @param progressMonitor Progress monitor to report progress during processing + * @param cbObj callback to call when processing is done. + **/ @Override public void run(DSPProgressMonitor progressMonitor, DSPCallback cbObj) { - logger.log(Level.INFO, "RAMAN run()..."); - callbackObj = cbObj; cancelled = false; if (!imageOptionsSet) { + // RAMAN TBD: we should ask the panel to save the current settings now + // get the image options from the panel imagePath = imageFilePanel.getContentPaths(); timeZone = imageFilePanel.getTimeZone(); @@ -124,24 +144,25 @@ public class ImageDSProcessor implements DataSourceProcessor { return; } - + + /** + * Cancel the data source processing + **/ @Override public void cancel() { - logger.log(Level.INFO, "RAMAN cancelProcessing()..."); - cancelled = true; addImageTask.cancelTask(); return; } - + /** + * Reset the data source processor + **/ @Override public void reset() { - logger.log(Level.INFO, "RAMAN reset()..."); - // reset the config panel imageFilePanel.reset(); @@ -154,6 +175,15 @@ public class ImageDSProcessor implements DataSourceProcessor { return; } + /** + * Sets the data source options externally. + * To be used by a client that does not have a UI and does not use the JPanel to + * collect this information from a user. + * + * @param imgPath path to thew image or first image + * @param String timeZone + * @param noFat whether to parse FAT orphans + **/ public void SetDataSourceOptions(String imgPath, String tz, boolean noFat) { this.imagePath = imgPath; @@ -164,7 +194,9 @@ 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()); @@ -193,14 +225,19 @@ public class ImageDSProcessor implements DataSourceProcessor { 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; @@ -209,7 +246,6 @@ public class ImageDSProcessor implements DataSourceProcessor { CurrentDirectoryFetcher(DSPProgressMonitor aProgressMonitor, SleuthkitJNI.CaseDbHandle.AddImageProcess proc) { this.progressMonitor = aProgressMonitor; this.process = proc; - // this.progressBar = aProgressBar; } /** @@ -252,15 +288,10 @@ public class ImageDSProcessor implements DataSourceProcessor { */ @Override protected Integer doInBackground() { - - logger.log(Level.INFO, "RAMAN: doInBackground()"); this.setProgress(0); errorList.clear(); - - - try { //lock DB for writes in EWT thread //wait until lock acquired in EWT @@ -315,8 +346,6 @@ public class ImageDSProcessor implements DataSourceProcessor { */ private void commitImage() throws Exception { - logger.log(Level.INFO, "RAMAN: commitImage()..."); - long imageId = 0; try { imageId = addImageProcess.commit(); @@ -352,43 +381,33 @@ public class ImageDSProcessor implements DataSourceProcessor { * * (called by EventDispatch Thread after doInBackground finishes) * - * Must Not return without invoking the callBack. + * Must Not return without invoking the callBack, unless the caller canceled */ @Override protected void done() { - - logger.log(Level.INFO, "RAMAN: done()..."); setProgress(100); - // cancel + // cancel the directory fetcher fetcher.cancel(true); - addImageDone = 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(); - // Do not return yet. Callback must be called } if (!errorList.isEmpty()) { - logger.log(Level.INFO, "Handling non-critical errors that occured in add image process"); - - // error are returned back to the caller } // When everything happens without an error: if (!(cancelled || hasCritError)) { try { - - - // Tell the panel we're done + // 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 @@ -408,8 +427,6 @@ public class ImageDSProcessor implements DataSourceProcessor { logger.log(Level.INFO, "Assuming image already committed, will not commit."); } - - } catch (Exception ex) { //handle unchecked exceptions post image add @@ -428,13 +445,14 @@ public class ImageDSProcessor implements DataSourceProcessor { if (!cancelled) doCallBack(); + return; } - - void doCallBack() - { - logger.log(Level.INFO, "RAMAN In doCallback()"); - + /* + * Call the callback with proper parameters + */ + private void doCallBack() + { DSPCallback.DSP_Result result; if (hasCritError) { @@ -446,14 +464,15 @@ public class ImageDSProcessor implements DataSourceProcessor { 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); } - - void cancelTask() { - - logger.log(Level.INFO, "RAMAN: cancelTask()..."); + /* + * cancel the image addition, if possible + */ + public void cancelTask() { cancelled = true; @@ -474,11 +493,11 @@ public class ImageDSProcessor implements DataSourceProcessor { } } } - void interrupt() throws Exception { + /* + * Interrurp the add image process if it is still running + */ + private void interrupt() throws Exception { - logger.log(Level.INFO, "RAMAN: interrupt()..."); - - //interrupted = true; try { logger.log(Level.INFO, "interrupt() add image process"); addImageProcess.stop(); //it might take time to truly stop processing and writing to db @@ -487,10 +506,11 @@ public class ImageDSProcessor implements DataSourceProcessor { } } - //runs in EWT + /* + * Revert - if image has already been added but not committed yet + */ void revert() { - logger.log(Level.INFO, "RAMAN: revert()..."); if (!reverted) { try { diff --git a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPCallback.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPCallback.java index 553cb71ebe..b5c4b7cba9 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPCallback.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPCallback.java @@ -9,8 +9,7 @@ import java.util.List; import org.sleuthkit.datamodel.Content; /** - * - * @author raman + * Abstract class for a callback */ public abstract class DSPCallback { @@ -21,6 +20,9 @@ public abstract class DSPCallback { NONCRITICAL_ERRORS, }; + /* + * Invoke the caller supplied callback function on the EDT thread + */ public void done(DSP_Result result, List errList, List newContents) { @@ -38,5 +40,8 @@ public abstract class DSPCallback { }); } + /* + * calling code overrides to provide its own calllback + */ public abstract void doneEDT(DSP_Result result, List errList, List newContents); }; From 1f7e98f28e95d9f79a5b40800cff955207c4173d Mon Sep 17 00:00:00 2001 From: raman-bt Date: Fri, 18 Oct 2013 12:22:57 -0400 Subject: [PATCH 09/21] 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; - } - } - } } From 6627dadd89a0000bffdef1305bcc0c0ba7af26db Mon Sep 17 00:00:00 2001 From: raman-bt Date: Fri, 18 Oct 2013 14:54:35 -0400 Subject: [PATCH 10/21] Added Copyright headers, added/cleaned up comments. --- .../autopsy/casemodule/AddImageTask.java | 28 +++++++++-- .../AddImageWizardIngestConfigPanel.java | 2 +- .../autopsy/casemodule/ImageDSProcessor.java | 38 +++++++-------- .../corecomponentinterfaces/DSPCallback.java | 25 ++++++++-- .../DSPProgressMonitor.java | 22 +++++++-- .../DataSourceProcessor.java | 47 +++++++++---------- 6 files changed, 105 insertions(+), 57 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java index def759ca5b..771d217eaa 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java @@ -1,7 +1,22 @@ /* - * To change this template, choose Tools | Templates - * and open the template in the editor. + * Autopsy Forensic Browser + * + * Copyright 2013 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ + package org.sleuthkit.autopsy.casemodule; import java.awt.EventQueue; @@ -23,6 +38,13 @@ import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskDataException; import org.sleuthkit.datamodel.TskException; +/* + * A background task (swingworker) that adds the given image to + * database using the Sleuthkit JNI interface. + * + * It updates the given ProgressMonitor as it works through adding the image, + * and et the end, calls the specified Callback. + */ public class AddImageTask extends SwingWorker { private Logger logger = Logger.getLogger(AddImageTask.class.getName()); @@ -275,7 +297,7 @@ public class AddImageTask extends SwingWorker { } /* - * Call the callback with proper parameters + * Call the callback with results, new content, and errors, if any */ private void doCallBack() { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java index a936b3294c..991e3fef5b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java @@ -296,7 +296,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.sleuthkit.autopsy.casemodule; -import java.awt.Color; -import java.awt.EventQueue; -import java.awt.Window; -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.JPanel; -import javax.swing.JProgressBar; -import javax.swing.SwingUtilities; -import javax.swing.SwingWorker; -import org.openide.WizardDescriptor; import org.openide.util.lookup.ServiceProvider; -import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; 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; import org.sleuthkit.autopsy.corecomponentinterfaces.DSPProgressMonitor; import org.sleuthkit.autopsy.corecomponentinterfaces.DSPCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; diff --git a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPCallback.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPCallback.java index b5c4b7cba9..f3bdf028da 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPCallback.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPCallback.java @@ -1,7 +1,22 @@ /* - * To change this template, choose Tools | Templates - * and open the template in the editor. + * Autopsy Forensic Browser + * + * Copyright 2013 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ + package org.sleuthkit.autopsy.corecomponentinterfaces; import java.awt.EventQueue; @@ -9,7 +24,11 @@ import java.util.List; import org.sleuthkit.datamodel.Content; /** - * Abstract class for a callback + * Abstract class for a callback for a DataSourceProcessor. + * + * Ensures that DSP invokes the caller overridden method, doneEDT(), + * in the EDT thread. + * */ public abstract class DSPCallback { diff --git a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPProgressMonitor.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPProgressMonitor.java index b375301aed..c68574eeb2 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPProgressMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPProgressMonitor.java @@ -1,13 +1,27 @@ /* - * To change this template, choose Tools | Templates - * and open the template in the editor. + * Autopsy Forensic Browser + * + * Copyright 2013 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.sleuthkit.autopsy.corecomponentinterfaces; /* - * An GUI agnostic DSPProgressMonitor interface for DataSorceProcesssors to + * An GUI agnostic DSPProgressMonitor interface for DataSourceProcesssors to * indicate progress. - * It models after a JProgressbar though could use any underlying implementation + * It models after a JProgressbar though it could use any underlying implementation */ public interface DSPProgressMonitor { diff --git a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessor.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessor.java index 59fc291c6e..4abce176b7 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessor.java @@ -18,19 +18,31 @@ */ package org.sleuthkit.autopsy.corecomponentinterfaces; -import java.util.List; + import javax.swing.JPanel; -import org.openide.WizardDescriptor; import org.sleuthkit.datamodel.Content; +/* + * Defines an interface used by the Add DataSource wizard to discover different + * Data SourceProcessors. + * A data source for Autopsy may be: + * - Disk Image (Encase, Raw....) + * - Local Disk + * - Logical file(s) + * - Phone Image + * - A CellXML file with content extracted from phone. + * + * Each data source may have its unique attributes and may need to be processed + * differently. + * + * The DataSourceProcessor interface defines a uniform mechanism for thre Autopsy UI + * to: + * - collect details for the data source to be processed. + * - Process the data source in the background + * - Be notified when the processing is complete + */ public interface DataSourceProcessor { - - - - - // public DataSourceProcessor createInstance(); - - + /** * Returns the type of Data Source it handles. * This name gets displayed in the drop-down listbox @@ -59,27 +71,14 @@ public interface DataSourceProcessor { **/ void run(DSPProgressMonitor progressPanel, DSPCallback dspCallback); - /** - * Called after run() is done to get the new content added by the handler. - * Returns a list of content added by the data source handler - **/ - // List getNewContents(); - - - /** - * Called to get the list of errors. - **/ - // String[] getErrors(); /** * Called to cancel the background processing. - * - * TODO look into current use cases to see if this should wait until it has stopped or not. **/ void cancel(); - /** - * Called to reset/reinit the DSP. + /** + * Called to reset/reinitialize the DSP. * **/ void reset(); From e91114c77cd793beb81a7ce03475e571f4c57359 Mon Sep 17 00:00:00 2001 From: raman-bt Date: Mon, 21 Oct 2013 11:09:47 -0400 Subject: [PATCH 11/21] i. Changed AddImageTask.CurrentDirFether to be a Runnable instead of Swingworker. ii. Changed the DSPProgressMonitorImpl to update the progress UI on the Swing EDT thread. iii. Added the image related params to AddImageTask constructor, and dropped the SetImageOptions() method. --- .../autopsy/casemodule/AddImageTask.java | 51 +++++++++---------- .../AddImageWizardAddingProgressPanel.java | 37 +++++++++++--- .../autopsy/casemodule/ImageDSProcessor.java | 8 +-- 3 files changed, 54 insertions(+), 42 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java index 771d217eaa..e7b6b05f34 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java @@ -55,7 +55,8 @@ public class AddImageTask extends SwingWorker { //true if revert has been invoked. private boolean reverted = false; private boolean hasCritError = false; - private boolean addImageDone = false; + + private boolean addImageDone = false; private List errorList = new ArrayList(); @@ -65,7 +66,7 @@ public class AddImageTask extends SwingWorker { private final List newContents = Collections.synchronizedList(new ArrayList()); private SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess; - private CurrentDirectoryFetcher fetcher; + private Thread dirFetcher; private String imagePath; private String dataSourcetype; @@ -73,20 +74,11 @@ public class AddImageTask extends SwingWorker { 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 { + private class CurrentDirectoryFetcher implements Runnable { DSPProgressMonitor progressMonitor; SleuthkitJNI.CaseDbHandle.AddImageProcess process; @@ -100,31 +92,33 @@ public class AddImageTask extends SwingWorker { * @return the currently processing directory */ @Override - protected Integer doInBackground() { + public void run() { try { - while (!(addImageDone)) { - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - progressMonitor.setText(process.currentDirectory()); - } - }); - + while (!Thread.currentThread().isInterrupted()) { + + progressMonitor.setText(process.currentDirectory()); + Thread.sleep(2 * 1000); } - return 1; + return; } catch (InterruptedException ie) { - return -1; + return; } } } - protected AddImageTask(DSPProgressMonitor aProgressMonitor, DSPCallback cbObj ) { - this.progressMonitor = aProgressMonitor; + protected AddImageTask(String imgPath, String tz, boolean noOrphans, DSPProgressMonitor aProgressMonitor, DSPCallback cbObj ) { + currentCase = Case.getCurrentCase(); + + this.imagePath = imgPath; + this.timeZone = tz; + this.noFatOrphans = noOrphans; + this.callbackObj = cbObj; + this.progressMonitor = aProgressMonitor; } /** @@ -159,13 +153,14 @@ public class AddImageTask extends SwingWorker { } addImageProcess = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans); - fetcher = new CurrentDirectoryFetcher(progressMonitor, addImageProcess); + dirFetcher = new Thread( new CurrentDirectoryFetcher(progressMonitor, addImageProcess)); try { progressMonitor.setIndeterminate(true); progressMonitor.setProgress(0); - fetcher.execute(); + dirFetcher.start(); + addImageProcess.run(new String[]{this.imagePath}); } catch (TskCoreException ex) { logger.log(Level.WARNING, "Core errors occurred while running add image. ", ex); @@ -237,7 +232,7 @@ public class AddImageTask extends SwingWorker { setProgress(100); // cancel the directory fetcher - fetcher.cancel(true); + dirFetcher.interrupt(); addImageDone = true; // attempt actions that might fail and force the process to stop diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java index 46592d269e..7e1bd20464 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.casemodule; import java.awt.Color; +import java.awt.EventQueue; import java.util.HashSet; import java.util.Iterator; import java.util.Set; @@ -60,20 +61,40 @@ class AddImageWizardAddingProgressPanel implements WizardDescriptor.FinishablePa private class DSPProgressMonitorImpl implements DSPProgressMonitor { @Override - public void setIndeterminate(boolean indeterminate) { - getComponent().getProgressBar().setIndeterminate(indeterminate); - + public void setIndeterminate(final boolean indeterminate) { + // update the progress bar asynchronously + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + getComponent().getProgressBar().setIndeterminate(indeterminate); + } + }); } + @Override - public void setProgress(int progress) { - getComponent().getProgressBar().setValue(progress); + public void setProgress(final int progress) { + // update the progress bar asynchronously + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + getComponent().getProgressBar().setValue(progress); + } + }); } + @Override - public void setText(String text) { - getComponent().setCurrentDirText(text); - + public void setText(final String text) { + // update the progress UI asynchronously + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + getComponent().setCurrentDirText(text); + } + }); } + + } /** * Get the visual component for the panel. In this template, the component diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java index 6540961af4..4fe759f3e5 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java @@ -121,7 +121,7 @@ public class ImageDSProcessor implements DataSourceProcessor { if (!imageOptionsSet) { - // RAMAN TBD: we should ask the panel to save the current settings now + // RAMAN TBD: we should ask the panel to save the current settings // get the image options from the panel imagePath = imageFilePanel.getContentPaths(); @@ -129,11 +129,7 @@ public class ImageDSProcessor implements DataSourceProcessor { noFatOrphans = imageFilePanel.getNoFatOrphans(); } - addImageTask = new AddImageTask(progressMonitor, cbObj); - - // set the image options needed by AddImageTask - such as TZ and NoFatOrphans **/ - addImageTask.SetImageOptions(imagePath, timeZone, noFatOrphans); - + addImageTask = new AddImageTask(imagePath, timeZone, noFatOrphans, progressMonitor, cbObj); addImageTask.execute(); return; From 4584640ec37d7ac4365b3c443e859c112ab65b05 Mon Sep 17 00:00:00 2001 From: raman-bt Date: Tue, 22 Oct 2013 10:53:11 -0400 Subject: [PATCH 12/21] Changed AddImageTask to be a plain Runnable instead of a SwingWorker. --- .../autopsy/casemodule/AddImageTask.java | 94 ++++++++----------- .../AddImageWizardIngestConfigPanel.java | 15 +-- .../sleuthkit/autopsy/casemodule/Case.java | 13 +++ .../autopsy/casemodule/ImageDSProcessor.java | 8 +- 4 files changed, 66 insertions(+), 64 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java index e7b6b05f34..6b611a6abc 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java @@ -45,18 +45,18 @@ import org.sleuthkit.datamodel.TskException; * It updates the given ProgressMonitor as it works through adding the image, * and et the end, calls the specified Callback. */ -public class AddImageTask extends SwingWorker { +public class AddImageTask implements Runnable { private Logger logger = Logger.getLogger(AddImageTask.class.getName()); private Case currentCase; // true if the process was requested to stop - private boolean cancelled = false; + private volatile boolean cancelled = false; //true if revert has been invoked. private boolean reverted = false; private boolean hasCritError = false; - private boolean addImageDone = false; + private volatile boolean addImageDone = false; private List errorList = new ArrayList(); @@ -112,7 +112,7 @@ public class AddImageTask extends SwingWorker { currentCase = Case.getCurrentCase(); - + this.imagePath = imgPath; this.timeZone = tz; this.noFatOrphans = noOrphans; @@ -129,29 +129,14 @@ public class AddImageTask extends SwingWorker { * @throws Exception */ @Override - protected Integer doInBackground() { + public void run() { - 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; - } + errorList.clear(); + + //lock DB for writes in this thread + SleuthkitCase.dbWriteLock(); + addImageProcess = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans); dirFetcher = new Thread( new CurrentDirectoryFetcher(progressMonitor, addImageProcess)); @@ -162,6 +147,7 @@ public class AddImageTask extends SwingWorker { dirFetcher.start(); 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 @@ -170,25 +156,28 @@ public class AddImageTask extends SwingWorker { } 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 - + } + finally { + } - return 0; + // handle addImage done + postProcess(); + + // unclock the DB + SleuthkitCase.dbWriteUnlock(); + + return; } /** - * Commit the finished AddImageProcess, and cancel the CleanupTask that - * would have reverted it. + * Commit the newly added image to DB * - * @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(); @@ -196,13 +185,11 @@ public class AddImageTask extends SwingWorker { 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); - + // get the newly added Image so we can return to caller + Image newImage = currentCase.getSleuthkitCase().getImageById(imageId); + //while we have the image, verify the size of its contents String verificationErrors = newImage.verifyImageSize(); if (verificationErrors.equals("") == false) { @@ -212,7 +199,6 @@ public class AddImageTask extends SwingWorker { // Add the image to the list of new content newContents.add(newImage); - } logger.log(Level.INFO, "Image committed, imageId: " + imageId); @@ -221,21 +207,18 @@ public class AddImageTask extends SwingWorker { } /** - * - * (called by EventDispatch Thread after doInBackground finishes) + * Post processing after the addImageProcess is done. * - * Must Not return without invoking the callBack, unless the caller canceled */ - @Override - protected void done() { - - setProgress(100); + private void postProcess() { + // cancel the directory fetcher dirFetcher.interrupt(); - + 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(); @@ -272,11 +255,9 @@ public class AddImageTask extends SwingWorker { } 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 { @@ -285,12 +266,15 @@ public class AddImageTask extends SwingWorker { } // invoke the callBack, unless the caller cancelled - if (!cancelled) + if (!cancelled) { doCallBack(); + } return; } + + /* * Call the callback with results, new content, and errors, if any */ @@ -354,8 +338,7 @@ public class AddImageTask extends SwingWorker { */ void revert() { - if (!reverted) { - + if (!reverted) { try { logger.log(Level.INFO, "Revert after add image process"); try { @@ -364,8 +347,7 @@ public class AddImageTask extends SwingWorker { 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/AddImageWizardIngestConfigPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java index 991e3fef5b..91e265e805 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java @@ -273,7 +273,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel errList, List contents) { - + // disable the cleanup task cleanupTask.disable(); @@ -286,7 +286,10 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel Date: Wed, 23 Oct 2013 08:44:21 -0400 Subject: [PATCH 13/21] Addressed review comments from Brian. --- .../AddImageWizardChooseDataSourceVisual.java | 24 +++++++++---------- .../AddImageWizardIngestConfigPanel.java | 2 +- .../autopsy/casemodule/ImageDSProcessor.java | 2 +- .../DataSourceProcessor.java | 6 ----- 4 files changed, 13 insertions(+), 21 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java index 92bb0d08ba..2bcea63a06 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java @@ -100,28 +100,26 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { typeComboBox.setSelectedIndex(0); typePanel.setLayout(new BorderLayout()); - updateCurrentPanel(GetCurrentDSProcessor().getPanel()); + updateCurrentPanel(getCurrentDSProcessor().getPanel()); } private void discoverDataSourceProcessors() { for (DataSourceProcessor dsProcessor: Lookup.getDefault().lookupAll(DataSourceProcessor.class)) { + if (!datasourceProcessorsMap.containsKey(dsProcessor.getType()) ) { - if (!datasourceProcessorsMap.containsKey(dsProcessor.getType()) ) { - - dsProcessor.reset(); - datasourceProcessorsMap.put(dsProcessor.getType(), dsProcessor); - } - else { - logger.log(Level.SEVERE, "discoverDataSourceProcessors(): A DataSourceProcessor already exists for type = " + dsProcessor.getType() ); - } - } + dsProcessor.reset(); + datasourceProcessorsMap.put(dsProcessor.getType(), dsProcessor); + } + else { + logger.log(Level.SEVERE, "discoverDataSourceProcessors(): A DataSourceProcessor already exists for type = " + dsProcessor.getType() ); + } } } private void dspSelectionChanged() { // update the current panel to selection - currentPanel = GetCurrentDSProcessor().getPanel(); + currentPanel = getCurrentDSProcessor().getPanel(); updateCurrentPanel(currentPanel); } @@ -155,7 +153,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { * Returns the currently selected DS Processor * @return DataSourceProcessor the DataSourceProcessor corresponding to the data source type selected in the combobox */ - public DataSourceProcessor GetCurrentDSProcessor() { + public DataSourceProcessor getCurrentDSProcessor() { // get the type of the currently selected panel and then look up // the correspodning DS Handler in the map String dsType = (String) typeComboBox.getSelectedItem(); @@ -296,7 +294,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { */ public void updateUI(DocumentEvent e) { // Enable the Next button if the current DSP panel is valid - String err = GetCurrentDSProcessor().validatePanel(); + String err = getCurrentDSProcessor().validatePanel(); if (null == err) this.wizPanel.enableNextButton(true); else diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java index 91e265e805..4392cc8498 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java @@ -244,7 +244,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel Date: Thu, 24 Oct 2013 15:52:39 -0400 Subject: [PATCH 14/21] Added LocalDiskDSProcessor and LocalFilesDSProcessor. Minor bugfixes & cleanup. --- .../autopsy/casemodule/AddImageTask.java | 4 +- .../AddImageWizardChooseDataSourceVisual.java | 6 +- .../autopsy/casemodule/AddLocalFilesTask.java | 186 +++++++++++++++++ .../autopsy/casemodule/Bundle.properties | 4 + .../autopsy/casemodule/ImageFilePanel.form | 2 +- .../autopsy/casemodule/ImageFilePanel.java | 2 +- .../casemodule/LocalDiskDSProcessor.java | 193 ++++++++++++++++++ .../autopsy/casemodule/LocalDiskPanel.form | 59 +++++- .../autopsy/casemodule/LocalDiskPanel.java | 141 +++++++++++-- .../casemodule/LocalFilesDSProcessor.java | 180 ++++++++++++++++ .../autopsy/casemodule/LocalFilesPanel.java | 7 +- 11 files changed, 749 insertions(+), 35 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java index 6b611a6abc..ff0a90a9c2 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java @@ -19,13 +19,11 @@ 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; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java index 2bcea63a06..867d617916 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java @@ -94,13 +94,11 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { } }; - typeComboBox.addActionListener(cbActionListener); - typeComboBox.setSelectedIndex(0); typePanel.setLayout(new BorderLayout()); - - updateCurrentPanel(getCurrentDSProcessor().getPanel()); + + typeComboBox.setSelectedIndex(0); } private void discoverDataSourceProcessors() { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java new file mode 100644 index 0000000000..ea70b783e3 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java @@ -0,0 +1,186 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.casemodule; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import org.sleuthkit.autopsy.corecomponentinterfaces.DSPCallback; +import org.sleuthkit.autopsy.corecomponentinterfaces.DSPProgressMonitor; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.autopsy.casemodule.services.FileManager; +import org.sleuthkit.datamodel.TskCoreException; + + +/** + * Thread that will add logical files to database, and then kick-off ingest + * modules. Note: the add logical files task cannot currently be reverted as + * the add image task can. This is a separate task from AddImgTask because + * it is much simpler and does not require locks, since the underlying file + * manager methods acquire the locks for each transaction when adding + * logical files. + */ +public class AddLocalFilesTask implements Runnable { + + private Logger logger = Logger.getLogger(AddLocalFilesTask.class.getName()); + + private String dataSourcePath; + private DSPProgressMonitor progressMonitor; + private DSPCallback callbackObj; + + private Case currentCase; + // true if the process was requested to stop + private volatile boolean cancelled = false; + private boolean hasCritError = false; + + private List errorList = new ArrayList(); + private final List newContents = Collections.synchronizedList(new ArrayList()); + + + protected AddLocalFilesTask(String dataSourcePath, DSPProgressMonitor aProgressMonitor, DSPCallback cbObj) { + + currentCase = Case.getCurrentCase(); + + this.dataSourcePath = dataSourcePath; + this.callbackObj = cbObj; + this.progressMonitor = aProgressMonitor; + } + + /** + * Starts the addImage process, but does not commit the results. + * + * @return + * + * @throws Exception + */ + @Override + public void run() { + errorList.clear(); + + // RAMAN TBD: dont we need to lock the DB ???? + + final LocalFilesAddProgressUpdater progUpdater = new LocalFilesAddProgressUpdater(progressMonitor); + try { + + progressMonitor.setIndeterminate(true); + progressMonitor.setProgress(0); + + final FileManager fileManager = currentCase.getServices().getFileManager(); + String[] paths = dataSourcePath.split(LocalFilesPanel.FILES_SEP); + List absLocalPaths = new ArrayList(); + for (String path : paths) { + absLocalPaths.add(path); + } + newContents.add(fileManager.addLocalFilesDirs(absLocalPaths, progUpdater)); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Errors occurred while running add logical files. ", ex); + hasCritError = true; + errorList.add(ex.getMessage()); + } finally { + + } + + // handle done + postProcess(); + + return; + } + + /** + * + * (called by EventDispatch Thread after doInBackground finishes) + */ + protected void postProcess() { + + if (cancelled || hasCritError) { + logger.log(Level.WARNING, "Handling errors or interruption that occured in logical files process"); + + } + if (!errorList.isEmpty()) { + //data error (non-critical) + logger.log(Level.WARNING, "Handling non-critical errors that occured in logical files process"); + } + + if (!(cancelled || hasCritError)) { + progressMonitor.setProgress(100); + progressMonitor.setIndeterminate(false); + } + + // invoke the callBack, unless the caller cancelled + if (!cancelled) { + doCallBack(); + } + + } + + /* + * Call the callback with results, new content, and errors, if any + */ + 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 callback, passing it the result, list of new contents, and list of errors + callbackObj.done(result, errorList, newContents); + } + + /* + * cancel the files addition, if possible + */ + public void cancelTask() { + cancelled = true; + + } + + /** + * Updates the wizard status with logical file/folder + */ + private class LocalFilesAddProgressUpdater implements FileManager.FileAddProgressUpdater { + + private int count = 0; + private DSPProgressMonitor progressMonitor; + + + LocalFilesAddProgressUpdater(DSPProgressMonitor progressMonitor) { + + this.progressMonitor = progressMonitor; + } + + @Override + public void fileAdded(final AbstractFile newFile) { + if (count++ % 10 == 0) { + progressMonitor.setText(newFile.getParentPath() + "/" + newFile.getName()); + } + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 6207163194..f7b76e175a 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -148,3 +148,7 @@ ImageFilePanel.timeZoneLabel.text=Please select the input timezone: ImageFilePanel.noFatOrphansCheckbox.text=Ignore orphan files in FAT file systems ImageFilePanel.noFatOrphansCheckbox.toolTipText= ImageFilePanel.descLabel.text=(faster results, although some data will not be searched) +LocalDiskPanel.timeZoneLabel.text=Please select the input timezone: +LocalDiskPanel.noFatOrphansCheckbox.toolTipText= +LocalDiskPanel.noFatOrphansCheckbox.text=Ignore orphan files in FAT file systems +LocalDiskPanel.descLabel.text=(faster results, although some data will not be searched) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form index b4dbaafd63..5d919e225a 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form @@ -66,7 +66,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java index 04a9d78767..c379f74f74 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java @@ -170,7 +170,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener { .addComponent(noFatOrphansCheckbox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(descLabel) - .addContainerGap(13, Short.MAX_VALUE)) + .addContainerGap(73, Short.MAX_VALUE)) ); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java new file mode 100644 index 0000000000..f268ef2b98 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java @@ -0,0 +1,193 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.sleuthkit.autopsy.casemodule; + +import javax.swing.JPanel; +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.corecomponentinterfaces.DSPCallback; +import org.sleuthkit.autopsy.corecomponentinterfaces.DSPProgressMonitor; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; +import org.sleuthkit.autopsy.coreutils.Logger; + + +@ServiceProvider(service = DataSourceProcessor.class) +public class LocalDiskDSProcessor implements DataSourceProcessor { + + static final Logger logger = Logger.getLogger(ImageDSProcessor.class.getName()); + + // Data source type handled by this processor + private final String dsType = "Local Disk"; + + // The Config UI panel that plugins into the Choose Data Source Wizard + private LocalDiskPanel localDiskPanel; + + // The Background task that does the actual work of adding the local Disk + // Adding a local disk is exactly same as adding an Image. + private AddImageTask addDiskTask; + + // true if cancelled by the caller + private boolean cancelled = false; + + DSPCallback callbackObj = null; + + // set to TRUE if the image options have been set via API and config Jpanel should be ignored + private boolean localDiskOptionsSet = false; + + // data source options + private String localDiskPath; + private String timeZone; + private boolean noFatOrphans; + + + + /* + * A no argument constructor is required for the NM lookup() method to create an object + */ + public LocalDiskDSProcessor() { + + // Create the config panel + localDiskPanel = LocalDiskPanel.getDefault(); + + } + + /** + * Returns the Data source type (string) handled by this DSP + * + * @return String the data source type + **/ + @Override + public String getType() { + return dsType; + } + + /** + * Returns the JPanel for collecting the Data source information + * + * @return JPanel the config panel + **/ + @Override + public JPanel getPanel() { + + // RAMAN TBD: we should ask the panel to preload with any saved settings + + localDiskPanel.select(); + return localDiskPanel; + } + /** + * Validates the data collected by the JPanel + * + * @return String returns NULL if success, error string if there is any errors + **/ + @Override + public String validatePanel() { + + if (localDiskPanel.validatePanel() ) + return null; + else + return "Error in panel"; + } + + + + /** + * Runs the data source processor. + * This must kick off processing the data source in background + * + * @param progressMonitor Progress monitor to report progress during processing + * @param cbObj callback to call when processing is done. + **/ + @Override + public void run(DSPProgressMonitor progressMonitor, DSPCallback cbObj) { + + callbackObj = cbObj; + cancelled = false; + + if (!localDiskOptionsSet) + { + // RAMAN TBD: we should ask the panel to save the current settings + + // get the image options from the panel + localDiskPath = localDiskPanel.getContentPaths(); + timeZone = localDiskPanel.getTimeZone(); + noFatOrphans = localDiskPanel.getNoFatOrphans(); + } + + addDiskTask = new AddImageTask(localDiskPath, timeZone, noFatOrphans, progressMonitor, cbObj); + new Thread(addDiskTask).start(); + + return; + } + + + + + + + + /** + * Cancel the data source processing + **/ + @Override + public void cancel() { + + cancelled = true; + + addDiskTask.cancelTask(); + + return; + } + + /** + * Reset the data source processor + **/ + @Override + public void reset() { + + // reset the config panel + localDiskPanel.reset(); + + // reset state + localDiskOptionsSet = false; + localDiskPath = null; + timeZone = null; + noFatOrphans = false; + + return; + } + + /** + * Sets the data source options externally. + * To be used by a client that does not have a UI and does not use the JPanel to + * collect this information from a user. + * + * @param diskPath path to the local disk + * @param String timeZone + * @param noFat whether to parse FAT orphans + **/ + public void setDataSourceOptions(String diskPath, String tz, boolean noFat) { + + this.localDiskPath = diskPath; + this.timeZone = tz; + this.noFatOrphans = noFat; + + localDiskOptionsSet = true; + + } +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form index a0b5f3f431..2b1062c834 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form @@ -29,8 +29,18 @@ + + + + + + + + + + - + @@ -40,8 +50,18 @@ - + + + + + + + + + + + @@ -71,5 +91,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java index a0ce4ec323..671622fdc7 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java @@ -25,7 +25,10 @@ import java.awt.Font; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.ArrayList; +import java.util.Calendar; import java.util.List; +import java.util.SimpleTimeZone; +import java.util.TimeZone; import java.util.concurrent.CancellationException; import java.util.logging.Level; import javax.swing.ComboBoxModel; @@ -43,7 +46,9 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil; /** * ImageTypePanel for adding a local disk or partition such as PhysicalDrive0 or C:. */ -public class LocalDiskPanel extends JPanel { +public class LocalDiskPanel extends JPanel { + private static final Logger logger = Logger.getLogger(LocalDiskPanel.class.getName()); + private static LocalDiskPanel instance; private PropertyChangeSupport pcs = null; private List disks = new ArrayList(); @@ -56,6 +61,9 @@ public class LocalDiskPanel extends JPanel { public LocalDiskPanel() { initComponents(); customInit(); + + createTimeZoneList(); + } /** @@ -73,8 +81,10 @@ public class LocalDiskPanel extends JPanel { model = new LocalDiskModel(); diskComboBox.setModel(model); diskComboBox.setRenderer(model); + errorLabel.setText(""); diskComboBox.setEnabled(false); + } /** @@ -89,6 +99,10 @@ public class LocalDiskPanel extends JPanel { diskLabel = new javax.swing.JLabel(); diskComboBox = new javax.swing.JComboBox(); errorLabel = new javax.swing.JLabel(); + timeZoneLabel = new javax.swing.JLabel(); + timeZoneComboBox = new javax.swing.JComboBox(); + noFatOrphansCheckbox = new javax.swing.JCheckBox(); + descLabel = new javax.swing.JLabel(); setMinimumSize(new java.awt.Dimension(0, 65)); setPreferredSize(new java.awt.Dimension(485, 65)); @@ -98,6 +112,15 @@ public class LocalDiskPanel extends JPanel { errorLabel.setForeground(new java.awt.Color(255, 0, 0)); org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.errorLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.timeZoneLabel.text")); // NOI18N + + timeZoneComboBox.setMaximumRowCount(30); + + org.openide.awt.Mnemonics.setLocalizedText(noFatOrphansCheckbox, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.noFatOrphansCheckbox.text")); // NOI18N + noFatOrphansCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.noFatOrphansCheckbox.toolTipText")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(descLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.descLabel.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -106,8 +129,16 @@ public class LocalDiskPanel extends JPanel { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(diskLabel) .addComponent(diskComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 345, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(errorLabel)) - .addGap(0, 140, Short.MAX_VALUE)) + .addComponent(errorLabel) + .addGroup(layout.createSequentialGroup() + .addComponent(timeZoneLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(noFatOrphansCheckbox) + .addGroup(layout.createSequentialGroup() + .addGap(21, 21, 21) + .addComponent(descLabel))) + .addGap(0, 102, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -115,14 +146,27 @@ public class LocalDiskPanel extends JPanel { .addComponent(diskLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(diskComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(13, 13, 13) + .addComponent(errorLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(timeZoneLabel) + .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(18, 18, 18) + .addComponent(noFatOrphansCheckbox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(errorLabel)) + .addComponent(descLabel) + .addContainerGap(27, Short.MAX_VALUE)) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel descLabel; private javax.swing.JComboBox diskComboBox; private javax.swing.JLabel diskLabel; private javax.swing.JLabel errorLabel; + private javax.swing.JCheckBox noFatOrphansCheckbox; + private javax.swing.JComboBox timeZoneComboBox; + private javax.swing.JLabel timeZoneLabel; // End of variables declaration//GEN-END:variables /** @@ -152,9 +196,14 @@ public class LocalDiskPanel extends JPanel { } } - //@Override - public String getContentType() { - return "DISK"; + public String getTimeZone() { + String tz = timeZoneComboBox.getSelectedItem().toString(); + return tz.substring(tz.indexOf(")") + 2).trim(); + + } + + boolean getNoFatOrphans() { + return noFatOrphansCheckbox.isSelected(); } /** @@ -163,22 +212,19 @@ public class LocalDiskPanel extends JPanel { * @return true */ //@Override - public boolean enableNext() { + public boolean validatePanel() { return enableNext; } //@Override public void reset() { //nothing to reset + + // RAMAN TBD this should reset the UI elements? + } - /** - * @return the representation of this panel as a String. - */ - //@Override - public String toString() { - return "Local Disk"; - } + /** * Set the focus to the diskComboBox and refreshes the list of disks. @@ -186,7 +232,8 @@ public class LocalDiskPanel extends JPanel { // @Override public void select() { diskComboBox.requestFocusInWindow(); - model.loadDisks(); + model.loadDisks(); + } @Override @@ -207,16 +254,61 @@ public class LocalDiskPanel extends JPanel { pcs.removePropertyChangeListener(pcl); } + /** + * Creates the drop down list for the time zones and then makes the local + * machine time zone to be selected. + */ + public void createTimeZoneList() { + // load and add all timezone + String[] ids = SimpleTimeZone.getAvailableIDs(); + for (String id : ids) { + TimeZone zone = TimeZone.getTimeZone(id); + int offset = zone.getRawOffset() / 1000; + int hour = offset / 3600; + int minutes = (offset % 3600) / 60; + String item = String.format("(GMT%+d:%02d) %s", hour, minutes, id); + + /* + * DateFormat dfm = new SimpleDateFormat("z"); + * dfm.setTimeZone(zone); boolean hasDaylight = + * zone.useDaylightTime(); String first = dfm.format(new Date(2010, + * 1, 1)); String second = dfm.format(new Date(2011, 6, 6)); int mid + * = hour * -1; String result = first + Integer.toString(mid); + * if(hasDaylight){ result = result + second; } + * timeZoneComboBox.addItem(item + " (" + result + ")"); + */ + timeZoneComboBox.addItem(item); + } + // get the current timezone + TimeZone thisTimeZone = Calendar.getInstance().getTimeZone(); + int thisOffset = thisTimeZone.getRawOffset() / 1000; + int thisHour = thisOffset / 3600; + int thisMinutes = (thisOffset % 3600) / 60; + String formatted = String.format("(GMT%+d:%02d) %s", thisHour, thisMinutes, thisTimeZone.getID()); + + // set the selected timezone + timeZoneComboBox.setSelectedItem(formatted); + } + private class LocalDiskModel implements ComboBoxModel, ListCellRenderer { private Object selected; private boolean ready = false; + private volatile boolean loadingDisks = false; List physical = new ArrayList(); List partitions = new ArrayList(); //private String SELECT = "Select a local disk:"; private String LOADING = "Loading local disks..."; + LocalDiskThread worker = null; + private void loadDisks() { + + // if there is a worker already building the lists, then cancel it first. + if (loadingDisks && worker != null) { + worker.cancel(false); + } + // Clear the lists errorLabel.setText(""); disks = new ArrayList(); @@ -224,9 +316,13 @@ public class LocalDiskPanel extends JPanel { partitions = new ArrayList(); diskComboBox.setEnabled(false); ready = false; - - LocalDiskThread worker = new LocalDiskThread(); + enableNext = false; + loadingDisks = true; + + worker = new LocalDiskThread(); worker.execute(); + + } @Override @@ -260,7 +356,7 @@ public class LocalDiskPanel extends JPanel { @Override public void removeListDataListener(ListDataListener l) { } - + @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { JPanel panel = new JPanel(new BorderLayout()); @@ -300,8 +396,6 @@ public class LocalDiskPanel extends JPanel { // Populate the lists physical = PlatformUtil.getPhysicalDrives(); partitions = PlatformUtil.getPartitions(); - disks.addAll(physical); - disks.addAll(partitions); return null; } @@ -337,6 +431,11 @@ public class LocalDiskPanel extends JPanel { enableNext = false; displayErrors(); ready = true; + worker = null; + loadingDisks = false; + + disks.addAll(physical); + disks.addAll(partitions); if(disks.size() > 0) { diskComboBox.setEnabled(true); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java new file mode 100644 index 0000000000..023b21259f --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java @@ -0,0 +1,180 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.sleuthkit.autopsy.casemodule; + +import javax.swing.JPanel; +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.corecomponentinterfaces.DSPCallback; +import org.sleuthkit.autopsy.corecomponentinterfaces.DSPProgressMonitor; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; +import org.sleuthkit.autopsy.coreutils.Logger; + +@ServiceProvider(service = DataSourceProcessor.class) +public class LocalFilesDSProcessor implements DataSourceProcessor { + + static final Logger logger = Logger.getLogger(LocalFilesDSProcessor.class.getName()); + + // Data source type handled by this processor + private final String dsType = "Logical Files"; + + // The Config UI panel that plugins into the Choose Data Source Wizard + private LocalFilesPanel localFilesPanel; + + // The Background task that does the actual work of adding the local Disk + // Adding a local disk is exactly same as adding an Image. + private AddLocalFilesTask addFilesTask; + + // true if cancelled by the caller + private boolean cancelled = false; + + DSPCallback callbackObj = null; + + // set to TRUE if the image options have been set via API and config Jpanel should be ignored + private boolean localFilesOptionsSet = false; + + // data source options + private String localFilesPath; + + + + /* + * A no argument constructor is required for the NM lookup() method to create an object + */ + public LocalFilesDSProcessor() { + + // Create the config panel + localFilesPanel = LocalFilesPanel.getDefault(); + + } + + /** + * Returns the Data source type (string) handled by this DSP + * + * @return String the data source type + **/ + @Override + public String getType() { + return dsType; + } + + /** + * Returns the JPanel for collecting the Data source information + * + * @return JPanel the config panel + **/ + @Override + public JPanel getPanel() { + + // RAMAN TBD: we should ask the panel to preload with any saved settings + + localFilesPanel.select(); + + return localFilesPanel; + } + /** + * Validates the data collected by the JPanel + * + * @return String returns NULL if success, error string if there is any errors + **/ + @Override + public String validatePanel() { + + if (localFilesPanel.validatePanel() ) + return null; + else + return "Error in panel"; + } + + + + /** + * Runs the data source processor. + * This must kick off processing the data source in background + * + * @param progressMonitor Progress monitor to report progress during processing + * @param cbObj callback to call when processing is done. + **/ + @Override + public void run(DSPProgressMonitor progressMonitor, DSPCallback cbObj) { + + callbackObj = cbObj; + cancelled = false; + + if (!localFilesOptionsSet) + { + // RAMAN TBD: we should ask the panel to save the current settings + + // get the image options from the panel + localFilesPath = localFilesPanel.getContentPaths(); + } + + addFilesTask = new AddLocalFilesTask(localFilesPath, progressMonitor, cbObj); + new Thread(addFilesTask).start(); + + return; + } + + /** + * Cancel the data source processing + **/ + @Override + public void cancel() { + + cancelled = true; + addFilesTask.cancelTask(); + + return; + } + + /** + * Reset the data source processor + **/ + @Override + public void reset() { + + // reset the config panel + localFilesPanel.reset(); + + // reset state + localFilesOptionsSet = false; + localFilesPath = null; + + + return; + } + + /** + * Sets the data source options externally. + * To be used by a client that does not have a UI and does not use the JPanel to + * collect this information from a user. + * + * @param filesPath PATH_SEP list of paths to local files + * + **/ + public void setDataSourceOptions(String filesPath) { + + this.localFilesPath = filesPath; + + localFilesOptionsSet = true; + + } + + +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java index 31b4877ff4..557f41fc87 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java @@ -85,7 +85,7 @@ public class LocalFilesPanel extends JPanel { } //@Override - public boolean enableNext() { + public boolean validatePanel() { return enableNext; } @@ -99,10 +99,11 @@ public class LocalFilesPanel extends JPanel { currentFiles.clear(); selectedPaths.setText(""); enableNext = false; - pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString(), false, true); + + //pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString(), false, true); } - @Override + @Override public synchronized void addPropertyChangeListener(PropertyChangeListener pcl) { super.addPropertyChangeListener(pcl); From 5e118737da5cd5443e5103d7d7b91366641250a5 Mon Sep 17 00:00:00 2001 From: raman-bt Date: Thu, 24 Oct 2013 17:01:56 -0400 Subject: [PATCH 15/21] i. Changed validatePanel() to return a boolean instead of string ii. Moved the UI Event/Property names into DataSourceProcessor to eliminate dependency on AddImageWizardChooseDataSourceVisual --- .../AddImageWizardChooseDataSourceVisual.java | 17 ++++----------- .../autopsy/casemodule/ImageDSProcessor.java | 7 ++----- .../autopsy/casemodule/ImageFilePanel.java | 9 ++++---- .../casemodule/LocalDiskDSProcessor.java | 8 ++----- .../autopsy/casemodule/LocalDiskPanel.java | 3 ++- .../casemodule/LocalFilesDSProcessor.java | 16 +++++--------- .../autopsy/casemodule/LocalFilesPanel.java | 3 ++- .../DataSourceProcessor.java | 21 ++++++++++++++----- 8 files changed, 38 insertions(+), 46 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java index 867d617916..42a49daf56 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java @@ -51,14 +51,9 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { static final Logger logger = Logger.getLogger(AddImageWizardChooseDataSourceVisual.class.getName()); - enum EVENT { - - UPDATE_UI, FOCUS_NEXT - }; - private AddImageWizardChooseDataSourcePanel wizPanel; - private JPanel currentPanel; + private JPanel currentPanel; private Map datasourceProcessorsMap = new HashMap(); @@ -135,10 +130,10 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { currentPanel.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString())) { + if (evt.getPropertyName().equals(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString())) { updateUI(null); } - if (evt.getPropertyName().equals(AddImageWizardChooseDataSourceVisual.EVENT.FOCUS_NEXT.toString())) { + if (evt.getPropertyName().equals(DataSourceProcessor.DSP_PANEL_EVENT.FOCUS_NEXT.toString())) { wizPanel.moveFocusToNext(); } } @@ -292,11 +287,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { */ public void updateUI(DocumentEvent e) { // Enable the Next button if the current DSP panel is valid - String err = getCurrentDSProcessor().validatePanel(); - if (null == err) - this.wizPanel.enableNextButton(true); - else - this.wizPanel.enableNextButton(false); + this.wizPanel.enableNextButton(getCurrentDSProcessor().validatePanel()); } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java index cb9f768ecc..fee952c05f 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java @@ -102,12 +102,9 @@ public class ImageDSProcessor implements DataSourceProcessor { * @return String returns NULL if success, error string if there is any errors **/ @Override - public String validatePanel() { + public boolean validatePanel() { - if (imageFilePanel.validatePanel() ) - return null; - else - return "Error in panel"; + return imageFilePanel.validatePanel(); } /** * Runs the data source processor. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java index c379f74f74..4be2a44483 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java @@ -31,6 +31,7 @@ import javax.swing.JFileChooser; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.JPanel; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; /** * ImageTypePanel for adding an image file such as .img, .E0x, .00x, etc. @@ -187,7 +188,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener { String path = fc.getSelectedFile().getPath(); pathTextField.setText(path); } - pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.FOCUS_NEXT.toString(), false, true); + pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.FOCUS_NEXT.toString(), false, true); }//GEN-LAST:event_browseButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables @@ -298,17 +299,17 @@ public class ImageFilePanel extends JPanel implements DocumentListener { */ @Override public void insertUpdate(DocumentEvent e) { - pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString(), false, true); + pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true); } @Override public void removeUpdate(DocumentEvent e) { - pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString(), false, true); + pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true); } @Override public void changedUpdate(DocumentEvent e) { - pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString(), false, true); + pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true); } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java index f268ef2b98..d6b8007fdb 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java @@ -96,12 +96,8 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { * @return String returns NULL if success, error string if there is any errors **/ @Override - public String validatePanel() { - - if (localDiskPanel.validatePanel() ) - return null; - else - return "Error in panel"; + public boolean validatePanel() { + return localDiskPanel.validatePanel(); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java index 671622fdc7..5b2e95ce04 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java @@ -40,6 +40,7 @@ import javax.swing.ListCellRenderer; import javax.swing.SwingWorker; import javax.swing.border.EmptyBorder; import javax.swing.event.ListDataListener; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.PlatformUtil; @@ -330,7 +331,7 @@ public class LocalDiskPanel extends JPanel { if(ready) { selected = anItem; enableNext = true; - pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString(), false, true); + pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true); } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java index 023b21259f..085c0b65c1 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java @@ -29,7 +29,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; @ServiceProvider(service = DataSourceProcessor.class) public class LocalFilesDSProcessor implements DataSourceProcessor { - static final Logger logger = Logger.getLogger(LocalFilesDSProcessor.class.getName()); + static final Logger logger = Logger.getLogger(LocalFilesDSProcessor.class.getName()); // Data source type handled by this processor private final String dsType = "Logical Files"; @@ -37,8 +37,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { // The Config UI panel that plugins into the Choose Data Source Wizard private LocalFilesPanel localFilesPanel; - // The Background task that does the actual work of adding the local Disk - // Adding a local disk is exactly same as adding an Image. + // The Background task that does the actual work of adding the files private AddLocalFilesTask addFilesTask; // true if cancelled by the caller @@ -60,8 +59,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { public LocalFilesDSProcessor() { // Create the config panel - localFilesPanel = LocalFilesPanel.getDefault(); - + localFilesPanel = LocalFilesPanel.getDefault(); } /** @@ -94,12 +92,8 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { * @return String returns NULL if success, error string if there is any errors **/ @Override - public String validatePanel() { - - if (localFilesPanel.validatePanel() ) - return null; - else - return "Error in panel"; + public boolean validatePanel() { + return localFilesPanel.validatePanel(); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java index 557f41fc87..c9cff7b1d0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java @@ -25,6 +25,7 @@ import java.util.Set; import java.util.TreeSet; import javax.swing.JFileChooser; import javax.swing.JPanel; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; /** * Add input wizard subpanel for adding local files / dirs to the case @@ -233,7 +234,7 @@ public class LocalFilesPanel extends JPanel { else { enableNext = false; } - pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString(), false, true); + pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true); }//GEN-LAST:event_selectButtonActionPerformed private void clearButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clearButtonActionPerformed diff --git a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessor.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessor.java index 581cd87b61..af67e78b68 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataSourceProcessor.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.corecomponentinterfaces; import javax.swing.JPanel; -import org.sleuthkit.datamodel.Content; /* * Defines an interface used by the Add DataSource wizard to discover different @@ -29,7 +28,7 @@ import org.sleuthkit.datamodel.Content; * Each data source may have its unique attributes and may need to be processed * differently. * - * The DataSourceProcessor interface defines a uniform mechanism for thre Autopsy UI + * The DataSourceProcessor interface defines a uniform mechanism for the Autopsy UI * to: * - collect details for the data source to be processed. * - Process the data source in the background @@ -37,6 +36,18 @@ import org.sleuthkit.datamodel.Content; */ public interface DataSourceProcessor { + /* + * The DSP Panel may fire Property change events + * The caller must enure to add itself as a listener and + * then react appropriately to the events + */ + enum DSP_PANEL_EVENT { + + UPDATE_UI, // the content of JPanel has changed that MAY warrant updates to the caller UI + FOCUS_NEXT // the caller UI may move focus the the next UI element, floowing the panel. + }; + + /** * Returns the type of Data Source it handles. * This name gets displayed in the drop-down listbox @@ -51,10 +62,10 @@ public interface DataSourceProcessor { /** * Called to validate the input data in the panel. - * Returns null if no errors, or - * Returns a string describing the error if there are errors. + * Returns true if no errors, or + * Returns false if there is an error. **/ - String validatePanel(); + boolean validatePanel(); /** * Called to invoke the handling of Data source in the background. From de7eb6b519ee7de788a8e7c5fbd9ecd3e7eee5a0 Mon Sep 17 00:00:00 2001 From: raman-bt Date: Mon, 28 Oct 2013 11:03:14 -0400 Subject: [PATCH 16/21] Straightened out the MissingImageDialog class w.r.t. DataSourceProcessor interface. MissingImageDialog allows the user to directly pick an image/local-disk if its is found to be missing. --- .../autopsy/casemodule/Bundle.properties | 3 +- .../sleuthkit/autopsy/casemodule/Case.java | 4 +- .../casemodule/MissingImageDialog.form | 64 +++--- .../casemodule/MissingImageDialog.java | 203 ++++++++---------- 4 files changed, 114 insertions(+), 160 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index f7b76e175a..53aba1d053 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -115,7 +115,6 @@ ImageFilePanel.browseButton.text=Browse ImageFilePanel.pathTextField.text= LocalDiskPanel.diskLabel.text=Select a local disk: MissingImageDialog.selectButton.text=Select Image -MissingImageDialog.typeTabel.text=Select input type to add: MissingImageDialog.titleLabel.text=Search for missing image MissingImageDialog.cancelButton.text=Cancel LocalDiskPanel.errorLabel.text=Error Label @@ -152,3 +151,5 @@ LocalDiskPanel.timeZoneLabel.text=Please select the input timezone: LocalDiskPanel.noFatOrphansCheckbox.toolTipText= LocalDiskPanel.noFatOrphansCheckbox.text=Ignore orphan files in FAT file systems LocalDiskPanel.descLabel.text=(faster results, although some data will not be searched) +MissingImageDialog.browseButton.text=Browse +MissingImageDialog.pathNameTextField.text= diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 63cfd6494d..1aedbc3124 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -319,9 +319,9 @@ public class Case implements SleuthkitCase.ErrorObserver { + "\nPlease note that you will still be able to browse directories and generate reports\n" + "if you choose No, but you will not be able to view file content or run the ingest process.", "Missing Image", JOptionPane.YES_NO_OPTION); if (ret == JOptionPane.YES_OPTION) { - /***** RAMAN TBD: MissingImageDialog class needs to be refactored to eliminate ContentTypePanel dependency. + MissingImageDialog.makeDialog(obj_id, db); - * *****************/ + } else { logger.log(Level.WARNING, "Selected image files don't match old files!"); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.form b/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.form index 24dd272951..d730da08dc 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.form @@ -110,65 +110,49 @@ - - - - - - - - - - + + + + + - + - - + + - - - + - - - - - - - - + - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java index d734444a57..deec62e813 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java @@ -18,42 +18,51 @@ */ package org.sleuthkit.autopsy.casemodule; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; + import java.awt.Dimension; import java.awt.Toolkit; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; import java.util.Arrays; import java.util.logging.Level; -import javax.swing.ComboBoxModel; -import javax.swing.JDialog; +import java.io.File; +import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.event.ListDataListener; -import org.openide.util.Exceptions; +import org.sleuthkit.autopsy.casemodule.ImageFilePanel; + import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; -/**** RAMAN TBD: this class needs to be straightened out. It should not duplicate what the ChooseDataSourceWizard does. + public class MissingImageDialog extends javax.swing.JDialog { private static final Logger logger = Logger.getLogger(MissingImageDialog.class.getName()); long obj_id; SleuthkitCase db; - ContentTypePanel currentPanel; - ImageTypeModel model; + + + + + private JFileChooser fc = new JFileChooser(); private MissingImageDialog(long obj_id, SleuthkitCase db) { super(new JFrame(), true); this.obj_id = obj_id; this.db = db; initComponents(); + + fc.setDragEnabled(false); + fc.setFileSelectionMode(JFileChooser.FILES_ONLY); + fc.setMultiSelectionEnabled(false); + + // borrow the filters from ImageFilePanel + fc.addChoosableFileFilter(ImageFilePanel.rawFilter); + fc.addChoosableFileFilter(ImageFilePanel.encaseFilter); + fc.setFileFilter(ImageFilePanel.allFilter); + + customInit(); } @@ -75,11 +84,8 @@ public class MissingImageDialog extends javax.swing.JDialog { } private void customInit() { - model = new ImageTypeModel(); - typeComboBox.setModel(model); - typeComboBox.setSelectedIndex(0); - typePanel.setLayout(new BorderLayout()); - updateCurrentPanel(ImageFilePanel.getDefault()); + + selectButton.setEnabled(false); } private void display() { @@ -94,35 +100,6 @@ public class MissingImageDialog extends javax.swing.JDialog { this.setVisible(true); } -// -// * Refresh this panel. -// * @param panel current typepanel -// - private void updateCurrentPanel(ContentTypePanel panel) { - currentPanel = panel; - typePanel.removeAll(); - typePanel.add((JPanel) currentPanel, BorderLayout.CENTER); - typePanel.validate(); - typePanel.repaint(); - this.validate(); - this.repaint(); - currentPanel.addPropertyChangeListener(new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if(evt.getPropertyName().equals(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString())) { - updateSelectButton(); - } - if(evt.getPropertyName().equals(AddImageWizardChooseDataSourceVisual.EVENT.FOCUS_NEXT.toString())) { - moveFocusToSelect(); - } - } - - }); - currentPanel.select(); - updateSelectButton(); - } - // // * Focuses the select button for easy enter-pressing access. // @@ -134,7 +111,13 @@ public class MissingImageDialog extends javax.swing.JDialog { // * Enables/disables the select button based off the current panel. // private void updateSelectButton() { - this.selectButton.setEnabled(currentPanel.enableNext()); + + // Enable this based on whether there is a valid path + if (!pathNameTextField.getText().isEmpty()) { + String filePath = pathNameTextField.getText(); + boolean isExist = Case.pathExists(filePath) || Case.driveExists(filePath); + selectButton.setEnabled(isExist); + } } // @@ -150,9 +133,8 @@ public class MissingImageDialog extends javax.swing.JDialog { selectButton = new javax.swing.JButton(); cancelButton = new javax.swing.JButton(); containerPanel = new javax.swing.JPanel(); - typeComboBox = new javax.swing.JComboBox(); - typeTabel = new javax.swing.JLabel(); - typePanel = new javax.swing.JPanel(); + pathNameTextField = new javax.swing.JTextField(); + browseButton = new javax.swing.JButton(); titleLabel = new javax.swing.JLabel(); titleSeparator = new javax.swing.JSeparator(); @@ -193,43 +175,39 @@ public class MissingImageDialog extends javax.swing.JDialog { .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); - org.openide.awt.Mnemonics.setLocalizedText(typeTabel, org.openide.util.NbBundle.getMessage(MissingImageDialog.class, "MissingImageDialog.typeTabel.text")); // NOI18N + pathNameTextField.setText(org.openide.util.NbBundle.getMessage(MissingImageDialog.class, "MissingImageDialog.pathNameTextField.text")); // NOI18N + pathNameTextField.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + pathNameTextFieldActionPerformed(evt); + } + }); - javax.swing.GroupLayout typePanelLayout = new javax.swing.GroupLayout(typePanel); - typePanel.setLayout(typePanelLayout); - typePanelLayout.setHorizontalGroup( - typePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 0, Short.MAX_VALUE) - ); - typePanelLayout.setVerticalGroup( - typePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 57, Short.MAX_VALUE) - ); + org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(MissingImageDialog.class, "MissingImageDialog.browseButton.text")); // NOI18N + browseButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + browseButtonActionPerformed(evt); + } + }); javax.swing.GroupLayout containerPanelLayout = new javax.swing.GroupLayout(containerPanel); containerPanel.setLayout(containerPanelLayout); containerPanelLayout.setHorizontalGroup( containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(containerPanelLayout.createSequentialGroup() - .addGap(10, 10, 10) - .addGroup(containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(typePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(containerPanelLayout.createSequentialGroup() - .addComponent(typeTabel) - .addGap(18, 18, 18) - .addComponent(typeComboBox, 0, 298, Short.MAX_VALUE))) - .addContainerGap()) + .addContainerGap() + .addComponent(pathNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 285, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(browseButton) + .addContainerGap(83, Short.MAX_VALUE)) ); containerPanelLayout.setVerticalGroup( containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(containerPanelLayout.createSequentialGroup() - .addGap(0, 0, 0) + .addGap(18, 18, 18) .addGroup(containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(typeTabel) - .addComponent(typeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(typePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addContainerGap()) + .addComponent(pathNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(browseButton)) + .addContainerGap(62, Short.MAX_VALUE)) ); titleLabel.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N @@ -270,7 +248,7 @@ public class MissingImageDialog extends javax.swing.JDialog { private void selectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectButtonActionPerformed try { - String newPath = currentPanel.getContentPaths(); + String newPath = pathNameTextField.getText(); //TODO handle local files db.setImagePaths(obj_id, Arrays.asList(new String[]{newPath})); } catch (TskCoreException ex) { @@ -283,16 +261,43 @@ public class MissingImageDialog extends javax.swing.JDialog { cancel(); }//GEN-LAST:event_cancelButtonActionPerformed + private void pathNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pathNameTextFieldActionPerformed + // TODO add your handling code here: + + updateSelectButton(); + }//GEN-LAST:event_pathNameTextFieldActionPerformed + + private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed + + + + String oldText = pathNameTextField.getText(); + + // set the current directory of the FileChooser if the ImagePath Field is valid + File currentDir = new File(oldText); + if (currentDir.exists()) { + fc.setCurrentDirectory(currentDir); + } + + int retval = fc.showOpenDialog(this); + if (retval == JFileChooser.APPROVE_OPTION) { + String path = fc.getSelectedFile().getPath(); + pathNameTextField.setText(path); + } + //pcs.firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.FOCUS_NEXT.toString(), false, true); + + updateSelectButton(); + }//GEN-LAST:event_browseButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton browseButton; private javax.swing.JPanel buttonPanel; private javax.swing.JButton cancelButton; private javax.swing.JPanel containerPanel; + private javax.swing.JTextField pathNameTextField; private javax.swing.JButton selectButton; private javax.swing.JLabel titleLabel; private javax.swing.JSeparator titleSeparator; - private javax.swing.JComboBox typeComboBox; - private javax.swing.JPanel typePanel; - private javax.swing.JLabel typeTabel; // End of variables declaration//GEN-END:variables // @@ -308,41 +313,5 @@ public class MissingImageDialog extends javax.swing.JDialog { } } -// -// * ComboBoxModel to control typeComboBox and supply ImageTypePanels. -// - private class ImageTypeModel implements ComboBoxModel { - ContentTypePanel selected; - ContentTypePanel[] types = ContentTypePanel.getPanels(); - @Override - public void setSelectedItem(Object anItem) { - selected = (ContentTypePanel) anItem; - updateCurrentPanel(selected); - } - - @Override - public Object getSelectedItem() { - return selected; - } - - @Override - public int getSize() { - return types.length; - } - - @Override - public Object getElementAt(int index) { - return types[index]; - } - - @Override - public void addListDataListener(ListDataListener l) { - } - - @Override - public void removeListDataListener(ListDataListener l) { - } - } -} -********************************/ \ No newline at end of file +} \ No newline at end of file From 0ce636ebf612d81407582e2d6915c04e1219bf0a Mon Sep 17 00:00:00 2001 From: raman-bt Date: Mon, 28 Oct 2013 15:48:27 -0400 Subject: [PATCH 17/21] Cleaned up the storing/reading of last selected data source path - delegated it to the DataSourceProcessor specific Panels, to handle as appropriate. --- .../AddImageWizardChooseDataSourcePanel.java | 22 ++---------- .../AddImageWizardIngestConfigPanel.java | 2 +- .../autopsy/casemodule/AddLocalFilesTask.java | 3 +- .../autopsy/casemodule/ImageDSProcessor.java | 9 ++--- .../autopsy/casemodule/ImageFilePanel.java | 34 ++++++++++++++----- .../casemodule/LocalDiskDSProcessor.java | 7 +--- .../autopsy/casemodule/LocalDiskPanel.java | 2 -- .../casemodule/LocalFilesDSProcessor.java | 13 ++----- 8 files changed, 38 insertions(+), 54 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java index 1588d865b5..d662439f3b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourcePanel.java @@ -180,16 +180,6 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel rawExt = Arrays.asList(new String[]{".img", ".dd", ".001", ".aa", ".raw"}); static final String rawDesc = "Raw Images (*.img, *.dd, *.001, *.aa, *.raw)"; static GeneralFilter rawFilter = new GeneralFilter(rawExt, rawDesc); @@ -71,6 +75,9 @@ public class ImageFilePanel extends JPanel implements DocumentListener { fc.addChoosableFileFilter(encaseFilter); fc.setFileFilter(allFilter); + + pcs = new PropertyChangeSupport(this); + createTimeZoneList(); } @@ -171,7 +178,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener { .addComponent(noFatOrphansCheckbox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(descLabel) - .addContainerGap(73, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -226,16 +233,11 @@ public class ImageFilePanel extends JPanel implements DocumentListener { return noFatOrphansCheckbox.isSelected(); } - public String getContentType() { - return "IMAGE"; - } + public void reset() { - //reset the UI elements to default - - pathTextField.setText(null); - - + //reset the UI elements to default + pathTextField.setText(null); } /** @@ -256,6 +258,20 @@ public class ImageFilePanel extends JPanel implements DocumentListener { } + public void storeSettings() { + + String imagePathName = getContentPaths(); + String imagePath = imagePathName.substring(0, imagePathName.lastIndexOf(File.separator) + 1); + + ModuleSettings.setConfigSetting(ImageFilePanel.class.getName(), PROP_LASTIMAGE_PATH, imagePath); + } + + public void readSettings() { + + String lastImagePath = ModuleSettings.getConfigSetting(ImageFilePanel.class.getName(), PROP_LASTIMAGE_PATH); + if (!lastImagePath.isEmpty()) + pathTextField.setText(lastImagePath); + } /** * Creates the drop down list for the time zones and then makes the local * machine time zone to be selected. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java index d6b8007fdb..325d9d9a2f 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java @@ -84,8 +84,6 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { **/ @Override public JPanel getPanel() { - - // RAMAN TBD: we should ask the panel to preload with any saved settings localDiskPanel.select(); return localDiskPanel; @@ -115,10 +113,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { callbackObj = cbObj; cancelled = false; - if (!localDiskOptionsSet) - { - // RAMAN TBD: we should ask the panel to save the current settings - + if (!localDiskOptionsSet) { // get the image options from the panel localDiskPath = localDiskPanel.getContentPaths(); timeZone = localDiskPanel.getTimeZone(); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java index 5b2e95ce04..22f1ed07f3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java @@ -221,8 +221,6 @@ public class LocalDiskPanel extends JPanel { public void reset() { //nothing to reset - // RAMAN TBD this should reset the UI elements? - } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java index 085c0b65c1..539bb2e050 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java @@ -79,11 +79,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { **/ @Override public JPanel getPanel() { - - // RAMAN TBD: we should ask the panel to preload with any saved settings - - localFilesPanel.select(); - + localFilesPanel.select(); return localFilesPanel; } /** @@ -111,11 +107,8 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { callbackObj = cbObj; cancelled = false; - if (!localFilesOptionsSet) - { - // RAMAN TBD: we should ask the panel to save the current settings - - // get the image options from the panel + if (!localFilesOptionsSet) { + // get the selected file paths from the panel localFilesPath = localFilesPanel.getContentPaths(); } From 657552661d9e875358b48afefedec87265ad480f Mon Sep 17 00:00:00 2001 From: raman-bt Date: Tue, 29 Oct 2013 09:24:21 -0400 Subject: [PATCH 18/21] i. Bugfix in readSettings() ii Adjusted the size of the Image & Local disk so they are fully visible in design view. --- .../autopsy/casemodule/ImageFilePanel.form | 2 +- .../autopsy/casemodule/ImageFilePanel.java | 18 ++++++++++-------- .../autopsy/casemodule/LocalDiskPanel.form | 2 +- .../autopsy/casemodule/LocalDiskPanel.java | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form index 5d919e225a..b201296bfa 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form @@ -66,7 +66,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java index 975665a4a1..c70b8f1f7f 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java @@ -40,6 +40,7 @@ import org.sleuthkit.autopsy.coreutils.ModuleSettings; */ public class ImageFilePanel extends JPanel implements DocumentListener { + private static final String PROP_LASTIMAGE_PATH = "LBL_LastImage_PATH"; static final List rawExt = Arrays.asList(new String[]{".img", ".dd", ".001", ".aa", ".raw"}); @@ -178,7 +179,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener { .addComponent(noFatOrphansCheckbox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(descLabel) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(33, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -259,18 +260,19 @@ public class ImageFilePanel extends JPanel implements DocumentListener { public void storeSettings() { - String imagePathName = getContentPaths(); - String imagePath = imagePathName.substring(0, imagePathName.lastIndexOf(File.separator) + 1); - - ModuleSettings.setConfigSetting(ImageFilePanel.class.getName(), PROP_LASTIMAGE_PATH, imagePath); + if (null != imagePathName ) { + String imagePath = imagePathName.substring(0, imagePathName.lastIndexOf(File.separator) + 1); + ModuleSettings.setConfigSetting(ImageFilePanel.class.getName(), PROP_LASTIMAGE_PATH, imagePath); + } } public void readSettings() { - String lastImagePath = ModuleSettings.getConfigSetting(ImageFilePanel.class.getName(), PROP_LASTIMAGE_PATH); - if (!lastImagePath.isEmpty()) - pathTextField.setText(lastImagePath); + if (null != lastImagePath) { + if (!lastImagePath.isEmpty()) + pathTextField.setText(lastImagePath); + } } /** * Creates the drop down list for the time zones and then makes the local diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form index 2b1062c834..58e493e793 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form @@ -61,7 +61,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java index 22f1ed07f3..ba746b7595 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java @@ -157,7 +157,7 @@ public class LocalDiskPanel extends JPanel { .addComponent(noFatOrphansCheckbox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(descLabel) - .addContainerGap(27, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables From 0b985703b738ee6b9af65dbb224917fbd9a3daa7 Mon Sep 17 00:00:00 2001 From: raman-bt Date: Tue, 29 Oct 2013 14:30:51 -0400 Subject: [PATCH 19/21] Ensure that the core DataSourceProcessors appear at the top in the wizard, and in a specific order. And there is a separator between 'core' DSPs and others. --- .../AddImageWizardChooseDataSourceVisual.java | 67 +++++++++++++++---- .../autopsy/casemodule/ImageDSProcessor.java | 2 +- .../casemodule/LocalDiskDSProcessor.java | 2 +- .../casemodule/LocalFilesDSProcessor.java | 2 +- 4 files changed, 58 insertions(+), 15 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java index 42a49daf56..dacec10e23 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java @@ -22,22 +22,20 @@ package org.sleuthkit.autopsy.casemodule; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.Component; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.SimpleTimeZone; -import java.util.TimeZone; import java.util.logging.Level; -import javax.swing.ComboBoxModel; import javax.swing.JPanel; +import javax.swing.JList; +import javax.swing.JSeparator; import javax.swing.event.DocumentEvent; -import javax.swing.event.ListDataListener; +import javax.swing.ListCellRenderer; import org.openide.util.Lookup; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; @@ -57,6 +55,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { private Map datasourceProcessorsMap = new HashMap(); + List coreDSPTypes = new ArrayList(); /** * Creates new form AddImageVisualPanel1 @@ -71,28 +70,49 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { } private void customInit() { + + typePanel.setLayout(new BorderLayout()); discoverDataSourceProcessors(); - + // set up the DSP type combobox typeComboBox.removeAllItems(); + Set dspTypes = datasourceProcessorsMap.keySet(); - for(String dspType:dspTypes){ + + // make a list of core DSPs + // ensure that the core DSPs are at the top and in a fixed order + coreDSPTypes.add(ImageDSProcessor.dsType); + coreDSPTypes.add(LocalDiskDSProcessor.dsType); + coreDSPTypes.add(LocalFilesDSProcessor.dsType); + + for(String dspType:coreDSPTypes){ typeComboBox.addItem(dspType); } + // now add any addtional DSPs that haven't already been added + for(String dspType:dspTypes){ + if (!coreDSPTypes.contains(dspType)) { + typeComboBox.addItem(dspType); + } + } + + // set a custom renderer that draws a separator at the end of the core DSPs in the combobox + typeComboBox.setRenderer(new ComboboxSeparatorRenderer(typeComboBox.getRenderer()){ + @Override + protected boolean addSeparatorAfter(JList list, Object value, int index){ + return (index == coreDSPTypes.size() - 1); + } + }); + //add actionlistner to listen for change ActionListener cbActionListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { dspSelectionChanged(); - } }; typeComboBox.addActionListener(cbActionListener); - - typePanel.setLayout(new BorderLayout()); - typeComboBox.setSelectedIndex(0); } @@ -290,4 +310,27 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel { this.wizPanel.enableNextButton(getCurrentDSProcessor().validatePanel()); } + + public abstract class ComboboxSeparatorRenderer implements ListCellRenderer{ + private ListCellRenderer delegate; + private JPanel separatorPanel = new JPanel(new BorderLayout()); + private JSeparator separator = new JSeparator(); + + public ComboboxSeparatorRenderer(ListCellRenderer delegate){ + this.delegate = delegate; + } + + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus){ + Component comp = delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if(index!=-1 && addSeparatorAfter(list, value, index)){ + separatorPanel.removeAll(); + separatorPanel.add(comp, BorderLayout.CENTER); + separatorPanel.add(separator, BorderLayout.SOUTH); + return separatorPanel; + }else + return comp; + } + + protected abstract boolean addSeparatorAfter(JList list, Object value, int index); + } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java index b82f59a4c6..0a56499828 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java @@ -40,7 +40,7 @@ public class ImageDSProcessor implements DataSourceProcessor { static final Logger logger = Logger.getLogger(ImageDSProcessor.class.getName()); // Data source type handled by this processor - private final String dsType = "Image File"; + protected final static String dsType = "Image File"; // The Config UI panel that plugins into the Choose Data Source Wizard private ImageFilePanel imageFilePanel; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java index 325d9d9a2f..cbaa520249 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java @@ -33,7 +33,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor { static final Logger logger = Logger.getLogger(ImageDSProcessor.class.getName()); // Data source type handled by this processor - private final String dsType = "Local Disk"; + static protected final String dsType = "Local Disk"; // The Config UI panel that plugins into the Choose Data Source Wizard private LocalDiskPanel localDiskPanel; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java index 539bb2e050..3c6089d4a3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java @@ -32,7 +32,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor { static final Logger logger = Logger.getLogger(LocalFilesDSProcessor.class.getName()); // Data source type handled by this processor - private final String dsType = "Logical Files"; + protected static final String dsType = "Logical Files"; // The Config UI panel that plugins into the Choose Data Source Wizard private LocalFilesPanel localFilesPanel; From 1bdc69dc1ea422d829f655665d107d2d41ab42cc Mon Sep 17 00:00:00 2001 From: raman-bt Date: Mon, 4 Nov 2013 12:47:44 -0500 Subject: [PATCH 20/21] Tweaked the ImageFilePanel so it can be used by any other DataSourceProcessor that needs an image path, a timezone string and the "no fat orphans" flag. --- .../AddImageWizardChooseDataSourceVisual.java | 4 +- .../autopsy/casemodule/GeneralFilter.java | 11 ++++ .../autopsy/casemodule/ImageDSProcessor.java | 32 +++++++++- .../autopsy/casemodule/ImageFilePanel.form | 2 +- .../autopsy/casemodule/ImageFilePanel.java | 64 +++++++++---------- .../casemodule/MissingImageDialog.java | 21 ++++-- 6 files changed, 90 insertions(+), 44 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java index dacec10e23..885b5cced0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardChooseDataSourceVisual.java @@ -41,8 +41,8 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; /** - * visual component for the first panel of add image wizard. Allows user to pick - * data source and timezone. + * visual component for the first panel of add image wizard. + * Allows the user to choose the data source type and then select the data source * */ final class AddImageWizardChooseDataSourceVisual extends JPanel { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java b/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java index b550a0a275..9b9a091466 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.casemodule; import java.io.File; import java.util.List; +import java.util.Arrays; import javax.swing.filechooser.FileFilter; /** @@ -28,6 +29,16 @@ import javax.swing.filechooser.FileFilter; */ public class GeneralFilter extends FileFilter{ + + // Extensions & Descriptions for commonly used filters + public static final List RAW_IMAGE_EXTS = Arrays.asList(new String[]{".img", ".dd", ".001", ".aa", ".raw", ".bin"}); + public static final String RAW_IMAGE_DESC = "Raw Images (*.img, *.dd, *.001, *.aa, *.raw, *.bin)"; + + public static final List ENCASE_IMAGE_EXTS = Arrays.asList(new String[]{".e01"}); + public static final String ENCASE_IMAGE_DESC = "Encase Images (*.e01)"; + + + private List extensions; private String desc; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java index 0a56499828..a60cf66468 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java @@ -21,6 +21,10 @@ package org.sleuthkit.autopsy.casemodule; import java.util.logging.Level; import javax.swing.JPanel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.swing.filechooser.FileFilter; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.corecomponentinterfaces.DSPProgressMonitor; @@ -37,6 +41,8 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; @ServiceProvider(service = DataSourceProcessor.class) public class ImageDSProcessor implements DataSourceProcessor { + + static final Logger logger = Logger.getLogger(ImageDSProcessor.class.getName()); // Data source type handled by this processor @@ -60,7 +66,29 @@ public class ImageDSProcessor implements DataSourceProcessor { private String imagePath; private String timeZone; private boolean noFatOrphans; - + + + + + static final GeneralFilter rawFilter = new GeneralFilter(GeneralFilter.RAW_IMAGE_EXTS, GeneralFilter.RAW_IMAGE_DESC); + static final GeneralFilter encaseFilter = new GeneralFilter(GeneralFilter.ENCASE_IMAGE_EXTS, GeneralFilter.ENCASE_IMAGE_DESC); + + static final List allExt = new ArrayList(); + static { + allExt.addAll(GeneralFilter.RAW_IMAGE_EXTS); + allExt.addAll(GeneralFilter.ENCASE_IMAGE_EXTS); + } + static final String allDesc = "All Supported Types"; + static final GeneralFilter allFilter = new GeneralFilter(allExt, allDesc); + + static final List filtersList = new ArrayList(); + + static { + filtersList.add(allFilter); + filtersList.add(rawFilter); + filtersList.add(encaseFilter); + } + /* * A no argument constructor is required for the NM lookup() method to create an object @@ -68,7 +96,7 @@ public class ImageDSProcessor implements DataSourceProcessor { public ImageDSProcessor() { // Create the config panel - imageFilePanel = ImageFilePanel.getDefault(); + imageFilePanel = ImageFilePanel.createInstance(ImageDSProcessor.class.getName(), filtersList); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form index b201296bfa..886767fa57 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.form @@ -66,7 +66,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java index c70b8f1f7f..03dd184e8c 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java @@ -31,6 +31,7 @@ import javax.swing.JFileChooser; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.JPanel; +import javax.swing.filechooser.FileFilter; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.coreutils.ModuleSettings; @@ -40,57 +41,52 @@ import org.sleuthkit.autopsy.coreutils.ModuleSettings; */ public class ImageFilePanel extends JPanel implements DocumentListener { - - private static final String PROP_LASTIMAGE_PATH = "LBL_LastImage_PATH"; + private final String PROP_LASTIMAGE_PATH = "LBL_LastImage_PATH"; - static final List rawExt = Arrays.asList(new String[]{".img", ".dd", ".001", ".aa", ".raw"}); - static final String rawDesc = "Raw Images (*.img, *.dd, *.001, *.aa, *.raw)"; - static GeneralFilter rawFilter = new GeneralFilter(rawExt, rawDesc); - static final List encaseExt = Arrays.asList(new String[]{".e01"}); - static final String encaseDesc = "Encase Images (*.e01)"; - static GeneralFilter encaseFilter = new GeneralFilter(encaseExt, encaseDesc); - static final List allExt = new ArrayList(); - - static { - allExt.addAll(rawExt); - allExt.addAll(encaseExt); - } - static final String allDesc = "All Supported Types"; - static GeneralFilter allFilter = new GeneralFilter(allExt, allDesc); - - - - private static ImageFilePanel instance = null; private PropertyChangeSupport pcs = null; private JFileChooser fc = new JFileChooser(); + + // Externally supplied name is used to store settings + private String contextName; /** * Creates new form ImageFilePanel + * @param context a string context name used to read/store last used settings + * @param fileChooserFilters a list of filters to be used with the FileChooser */ - public ImageFilePanel() { + private ImageFilePanel(String context, List fileChooserFilters) { initComponents(); fc.setDragEnabled(false); fc.setFileSelectionMode(JFileChooser.FILES_ONLY); fc.setMultiSelectionEnabled(false); - fc.addChoosableFileFilter(rawFilter); - fc.addChoosableFileFilter(encaseFilter); - fc.setFileFilter(allFilter); + boolean firstFilter = true; + for (FileFilter filter: fileChooserFilters ) { + if (firstFilter) { // set the first on the list as the default selection + fc.setFileFilter(filter); + firstFilter = false; + } + else { + fc.addChoosableFileFilter(filter); + } + } + this.contextName = context; pcs = new PropertyChangeSupport(this); createTimeZoneList(); } /** - * Returns the default instance of a ImageFilePanel. + * Creates and returns an instance of a ImageFilePanel. */ - public static synchronized ImageFilePanel getDefault() { - if (instance == null) { - instance = new ImageFilePanel(); - instance.postInit(); - } - return instance; + public static synchronized ImageFilePanel createInstance(String context, List fileChooserFilters) { + + ImageFilePanel instance = new ImageFilePanel(context, fileChooserFilters ); + + instance.postInit(); + + return instance; } //post-constructor initialization to properly initialize listener support @@ -230,7 +226,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener { } - boolean getNoFatOrphans() { + public boolean getNoFatOrphans() { return noFatOrphansCheckbox.isSelected(); } @@ -263,12 +259,12 @@ public class ImageFilePanel extends JPanel implements DocumentListener { String imagePathName = getContentPaths(); if (null != imagePathName ) { String imagePath = imagePathName.substring(0, imagePathName.lastIndexOf(File.separator) + 1); - ModuleSettings.setConfigSetting(ImageFilePanel.class.getName(), PROP_LASTIMAGE_PATH, imagePath); + ModuleSettings.setConfigSetting(contextName, PROP_LASTIMAGE_PATH, imagePath); } } public void readSettings() { - String lastImagePath = ModuleSettings.getConfigSetting(ImageFilePanel.class.getName(), PROP_LASTIMAGE_PATH); + String lastImagePath = ModuleSettings.getConfigSetting(contextName, PROP_LASTIMAGE_PATH); if (null != lastImagePath) { if (!lastImagePath.isEmpty()) pathTextField.setText(lastImagePath); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java index deec62e813..d54c52fc4b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MissingImageDialog.java @@ -24,12 +24,14 @@ import java.awt.Toolkit; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Arrays; +import java.util.List; +import java.util.ArrayList; import java.util.logging.Level; import java.io.File; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JOptionPane; -import org.sleuthkit.autopsy.casemodule.ImageFilePanel; +import org.sleuthkit.autopsy.casemodule.GeneralFilter; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.SleuthkitCase; @@ -44,6 +46,16 @@ public class MissingImageDialog extends javax.swing.JDialog { + static final GeneralFilter rawFilter = new GeneralFilter(GeneralFilter.RAW_IMAGE_EXTS, GeneralFilter.RAW_IMAGE_DESC); + static final GeneralFilter encaseFilter = new GeneralFilter(GeneralFilter.ENCASE_IMAGE_EXTS, GeneralFilter.ENCASE_IMAGE_DESC); + + static final List allExt = new ArrayList(); + static { + allExt.addAll(GeneralFilter.RAW_IMAGE_EXTS); + allExt.addAll(GeneralFilter.ENCASE_IMAGE_EXTS); + } + static final String allDesc = "All Supported Types"; + static final GeneralFilter allFilter = new GeneralFilter(allExt, allDesc); private JFileChooser fc = new JFileChooser(); @@ -57,10 +69,9 @@ public class MissingImageDialog extends javax.swing.JDialog { fc.setFileSelectionMode(JFileChooser.FILES_ONLY); fc.setMultiSelectionEnabled(false); - // borrow the filters from ImageFilePanel - fc.addChoosableFileFilter(ImageFilePanel.rawFilter); - fc.addChoosableFileFilter(ImageFilePanel.encaseFilter); - fc.setFileFilter(ImageFilePanel.allFilter); + fc.addChoosableFileFilter(rawFilter); + fc.addChoosableFileFilter(encaseFilter); + fc.setFileFilter(allFilter); customInit(); From a4fc68b5a86ddb70e32329286618fa1869a2ca31 Mon Sep 17 00:00:00 2001 From: raman-bt Date: Wed, 13 Nov 2013 09:14:26 -0500 Subject: [PATCH 21/21] Changed the label on the message box in ProgressPanel to be more generic and read "Status" instead of "Currently Adding:" Any kind of progress messages may be displayed in the box, instead of simply the name of file/folder being added. --- .../autopsy/casemodule/AddImageTask.java | 9 ++++-- .../AddImageWizardAddingProgressPanel.java | 4 +-- .../AddImageWizardAddingProgressVisual.form | 10 +++--- .../AddImageWizardAddingProgressVisual.java | 32 +++++++++---------- .../AddImageWizardIngestConfigPanel.java | 17 ---------- .../autopsy/casemodule/AddLocalFilesTask.java | 2 +- .../autopsy/casemodule/Bundle.properties | 2 +- .../DSPProgressMonitor.java | 2 +- 8 files changed, 32 insertions(+), 46 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java index ff0a90a9c2..ed2ef603b6 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java @@ -93,9 +93,12 @@ public class AddImageTask implements Runnable { public void run() { try { while (!Thread.currentThread().isInterrupted()) { - - progressMonitor.setText(process.currentDirectory()); - + String currDir = process.currentDirectory(); + if (currDir != null) { + if (!currDir.isEmpty() ) { + progressMonitor.setProgressText("Adding: " + currDir); + } + } Thread.sleep(2 * 1000); } return; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java index 7e1bd20464..476bbdd1df 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java @@ -83,12 +83,12 @@ class AddImageWizardAddingProgressPanel implements WizardDescriptor.FinishablePa } @Override - public void setText(final String text) { + public void setProgressText(final String text) { // update the progress UI asynchronously EventQueue.invokeLater(new Runnable() { @Override public void run() { - getComponent().setCurrentDirText(text); + getComponent().setProgressMsgText(text); } }); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressVisual.form b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressVisual.form index 53febaf0bf..9f3068809b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressVisual.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressVisual.form @@ -142,7 +142,7 @@ - + @@ -158,7 +158,7 @@ - + @@ -185,7 +185,7 @@ - + @@ -196,11 +196,11 @@ - + - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressVisual.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressVisual.java index a95ad671f2..f0e10fa1e2 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressVisual.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressVisual.java @@ -71,7 +71,7 @@ public class AddImageWizardAddingProgressVisual extends javax.swing.JPanel { donePanel.setVisible(false); viewLogButton.setVisible(false); //match visual background of panel - this.TextArea_CurrentDirectory.setBackground(this.getBackground()); + this.progressTextArea.setBackground(this.getBackground()); } @@ -95,10 +95,10 @@ public class AddImageWizardAddingProgressVisual extends javax.swing.JPanel { /** * Updates the currently processing directory * - * @param dir the text to update with + * @param msg the text to update with */ - public void setCurrentDirText(String dir) { - this.TextArea_CurrentDirectory.setText(dir); + public void setProgressMsgText(String msg) { + this.progressTextArea.setText(msg); } /** @@ -140,7 +140,7 @@ public class AddImageWizardAddingProgressVisual extends javax.swing.JPanel { inProgressPanel = new javax.swing.JPanel(); progressBar = new javax.swing.JProgressBar(); progressLabel = new javax.swing.JLabel(); - TextArea_CurrentDirectory = new javax.swing.JTextArea(); + progressTextArea = new javax.swing.JTextArea(); subTitle2Label = new javax.swing.JLabel(); subTitle1Label = new javax.swing.JLabel(); @@ -193,14 +193,14 @@ public class AddImageWizardAddingProgressVisual extends javax.swing.JPanel { org.openide.awt.Mnemonics.setLocalizedText(progressLabel, org.openide.util.NbBundle.getMessage(AddImageWizardAddingProgressVisual.class, "AddImageWizardAddingProgressVisual.progressLabel.text")); // NOI18N progressLabel.setPreferredSize(null); - TextArea_CurrentDirectory.setEditable(false); - TextArea_CurrentDirectory.setBackground(new java.awt.Color(240, 240, 240)); - TextArea_CurrentDirectory.setLineWrap(true); - TextArea_CurrentDirectory.setRows(5); - TextArea_CurrentDirectory.setWrapStyleWord(true); - TextArea_CurrentDirectory.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), org.openide.util.NbBundle.getMessage(AddImageWizardAddingProgressVisual.class, "AddImageWizardAddingProgressVisual.TextArea_CurrentDirectory.border.title"))); // NOI18N - TextArea_CurrentDirectory.setCursor(new java.awt.Cursor(java.awt.Cursor.TEXT_CURSOR)); - TextArea_CurrentDirectory.setFocusable(false); + progressTextArea.setEditable(false); + progressTextArea.setBackground(new java.awt.Color(240, 240, 240)); + progressTextArea.setLineWrap(true); + progressTextArea.setRows(5); + progressTextArea.setWrapStyleWord(true); + progressTextArea.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), org.openide.util.NbBundle.getMessage(AddImageWizardAddingProgressVisual.class, "AddImageWizardAddingProgressVisual.progressTextArea.border.title"))); // NOI18N + progressTextArea.setCursor(new java.awt.Cursor(java.awt.Cursor.TEXT_CURSOR)); + progressTextArea.setFocusable(false); org.openide.awt.Mnemonics.setLocalizedText(subTitle2Label, org.openide.util.NbBundle.getMessage(AddImageWizardAddingProgressVisual.class, "AddImageWizardAddingProgressVisual.subTitle2Label.text")); // NOI18N @@ -216,7 +216,7 @@ public class AddImageWizardAddingProgressVisual extends javax.swing.JPanel { .addComponent(subTitle2Label) .addComponent(progressLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(subTitle1Label, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(TextArea_CurrentDirectory) + .addComponent(progressTextArea) .addComponent(progressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGap(0, 8, Short.MAX_VALUE)) ); @@ -229,7 +229,7 @@ public class AddImageWizardAddingProgressVisual extends javax.swing.JPanel { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(TextArea_CurrentDirectory, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(progressTextArea, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(progressLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap()) @@ -268,12 +268,12 @@ public class AddImageWizardAddingProgressVisual extends javax.swing.JPanel { dialog.setVisible(true); }//GEN-LAST:event_viewLogButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables - protected javax.swing.JTextArea TextArea_CurrentDirectory; protected javax.swing.JPanel donePanel; protected javax.swing.JPanel inProgressPanel; private javax.swing.JPanel loadingPanel; private javax.swing.JProgressBar progressBar; protected javax.swing.JLabel progressLabel; + protected javax.swing.JTextArea progressTextArea; protected javax.swing.JLabel statusLabel; protected javax.swing.JLabel subTitle1Label; protected javax.swing.JLabel subTitle2Label; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java index 917ff4316e..4e7ed87ab6 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java @@ -22,36 +22,19 @@ package org.sleuthkit.autopsy.casemodule; import org.sleuthkit.autopsy.ingest.IngestConfigurator; import java.awt.Color; import java.awt.Component; -import java.awt.EventQueue; import java.awt.Window; -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.JButton; import javax.swing.JOptionPane; -import javax.swing.JProgressBar; import javax.swing.SwingUtilities; -import javax.swing.SwingWorker; import javax.swing.event.ChangeListener; import org.openide.WizardDescriptor; import org.openide.util.HelpCtx; import org.openide.util.Lookup; -import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.PlatformUtil; -import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.FileSystem; -import org.sleuthkit.datamodel.Image; -import org.sleuthkit.datamodel.SleuthkitCase; -import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess; -import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.TskDataException; -import org.sleuthkit.datamodel.TskException; -import org.sleuthkit.datamodel.Volume; -import org.sleuthkit.datamodel.VolumeSystem; import org.sleuthkit.autopsy.corecomponentinterfaces.DSPCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java index 7d6a3c0668..34b7a32089 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java @@ -178,7 +178,7 @@ public class AddLocalFilesTask implements Runnable { @Override public void fileAdded(final AbstractFile newFile) { if (count++ % 10 == 0) { - progressMonitor.setText(newFile.getParentPath() + "/" + newFile.getName()); + progressMonitor.setProgressText("Adding: " + newFile.getParentPath() + "/" + newFile.getName()); } } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 53aba1d053..1c20ec4025 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -138,7 +138,6 @@ AddImageWizardChooseDataSourceVisual.jLabel2.text=jLabel2 AddImageWizardChooseDataSourceVisual.nextLabel.text= Press 'Next' to analyze the input data, extract volume and file system data, and populate a local database. AddImageWizardChooseDataSourceVisual.imgInfoLabel.text=Enter Data Source Information: AddImageWizardAddingProgressVisual.progressLabel.text= -AddImageWizardAddingProgressVisual.TextArea_CurrentDirectory.border.title=Currently Adding: AddImageWizardAddingProgressVisual.viewLogButton.text=View Log AddImageWizardAddingProgressVisual.titleLabel.text=Adding Data Source AddImageWizardAddingProgressVisual.subTitle1Label.text=File system information is being added to a local database. File analysis will start when this finishes. @@ -153,3 +152,4 @@ LocalDiskPanel.noFatOrphansCheckbox.text=Ignore orphan files in FAT file systems LocalDiskPanel.descLabel.text=(faster results, although some data will not be searched) MissingImageDialog.browseButton.text=Browse MissingImageDialog.pathNameTextField.text= +AddImageWizardAddingProgressVisual.progressTextArea.border.title=Status diff --git a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPProgressMonitor.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPProgressMonitor.java index c68574eeb2..88d6b5e04c 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPProgressMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DSPProgressMonitor.java @@ -29,5 +29,5 @@ public interface DSPProgressMonitor { void setProgress(int progress); - void setText(String text); + void setProgressText(String text); }