mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 02:07:42 +00:00
Cleanup of Add Image/DataSource Wizard. Pass #1.
This commit is contained in:
parent
3415a54e99
commit
7b52520f90
@ -43,6 +43,7 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<Wiza
|
||||
* The visual component that displays this panel. If you need to access the
|
||||
* component from this class, just use getComponent().
|
||||
*/
|
||||
private AddImageWizardAddingProgressPanel progressPanel;
|
||||
private AddImageWizardChooseDataSourceVisual component;
|
||||
private boolean isNextEnable = false;
|
||||
private static final String PROP_LASTDATASOURCE_PATH = "LBL_LastDataSource_PATH";
|
||||
@ -50,6 +51,12 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<Wiza
|
||||
// paths to any set hash lookup databases (can be null)
|
||||
private String NSRLPath, knownBadPath;
|
||||
|
||||
|
||||
AddImageWizardChooseDataSourcePanel(AddImageWizardAddingProgressPanel proPanel) {
|
||||
|
||||
this.progressPanel = proPanel;
|
||||
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
|
@ -24,14 +24,20 @@ 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.SimpleTimeZone;
|
||||
import java.util.TimeZone;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.ListDataListener;
|
||||
import org.sleuthkit.autopsy.casemodule.ContentTypePanel.ContentType;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.casemodule.ContentTypePanel;
|
||||
//import org.sleuthkit.autopsy.casemodule.ContentTypePanel.ContentType;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* visual component for the first panel of add image wizard. Allows user to pick
|
||||
@ -40,6 +46,8 @@ import org.sleuthkit.autopsy.casemodule.ContentTypePanel.ContentType;
|
||||
*/
|
||||
final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
|
||||
static final Logger logger = Logger.getLogger(AddImageWizardChooseDataSourceVisual.class.getName());
|
||||
|
||||
enum EVENT {
|
||||
|
||||
UPDATE_UI, FOCUS_NEXT
|
||||
@ -61,6 +69,10 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
private AddImageWizardChooseDataSourcePanel wizPanel;
|
||||
private ContentTypeModel model;
|
||||
private ContentTypePanel currentPanel;
|
||||
|
||||
static private Map<String, DataSourceProcessor> datasourceProcessorsMap = new HashMap<String, DataSourceProcessor>();;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
|
@ -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<WizardDe
|
||||
private boolean readyToIngest = false;
|
||||
// the paths of the image files to be added
|
||||
private String dataSourcePath;
|
||||
private ContentType dataSourceType;
|
||||
private String dataSourceType;
|
||||
// the time zone where the image is added
|
||||
private String timeZone;
|
||||
//whether to not process FAT filesystem orphans
|
||||
@ -82,14 +82,19 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
private AddImageAction.CleanupTask cleanupImage; // initialized to null in readSettings()
|
||||
private CurrentDirectoryFetcher fetcher;
|
||||
private AddImageProcess process;
|
||||
private AddImageAction action;
|
||||
private AddImageAction addImageAction;
|
||||
private AddImageTask addImageTask;
|
||||
private AddLocalFilesTask addLocalFilesTask;
|
||||
private AddImageWizardAddingProgressPanel progressPanel;
|
||||
private AddImageWizardChooseDataSourcePanel dataSourcePanel;
|
||||
private DataSourceProcessor dsProcessor;
|
||||
private AddImageAction.CleanupTask cleanupTask;
|
||||
|
||||
AddImageWizardIngestConfigPanel(AddImageAction action, AddImageWizardAddingProgressPanel proPanel) {
|
||||
this.action = action;
|
||||
AddImageWizardIngestConfigPanel(AddImageWizardChooseDataSourcePanel dsPanel, AddImageAction action, AddImageWizardAddingProgressPanel proPanel) {
|
||||
this.addImageAction = action;
|
||||
this.progressPanel = proPanel;
|
||||
this.dataSourcePanel = dsPanel;
|
||||
|
||||
ingestConfig = Lookup.getDefault().lookup(IngestConfigurator.class);
|
||||
List<String> messages = ingestConfig.setContext(AddImageWizardIngestConfigPanel.class.getCanonicalName());
|
||||
if (messages.isEmpty() == false) {
|
||||
@ -188,12 +193,13 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
|
||||
newContents.clear();
|
||||
dataSourcePath = (String) settings.getProperty(AddImageAction.DATASOURCEPATH_PROP);
|
||||
dataSourceType = (ContentType) settings.getProperty(AddImageAction.DATASOURCETYPE_PROP);
|
||||
dataSourceType = (String) settings.getProperty(AddImageAction.DATASOURCETYPE_PROP);
|
||||
timeZone = settings.getProperty(AddImageAction.TIMEZONE_PROP).toString();
|
||||
noFatOrphans = ((Boolean) settings.getProperty(AddImageAction.NOFATORPHANS_PROP)).booleanValue();
|
||||
|
||||
//start the process of adding the content
|
||||
if (dataSourceType.equals(ContentType.LOCAL)) {
|
||||
/*******
|
||||
if (dataSourceType.equals("LOCAL")) {
|
||||
addLocalFilesTask = new AddLocalFilesTask(settings);
|
||||
addLocalFilesTask.execute();
|
||||
} else {
|
||||
@ -201,6 +207,9 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
addImageTask = new AddImageTask(settings);
|
||||
addImageTask.execute();
|
||||
}
|
||||
* ********/
|
||||
|
||||
startDataSourceProcessing(settings);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -233,8 +242,75 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
progressPanel.setStateFinished();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the Data source handling by kicking of the selected DataSourceProcessor
|
||||
*/
|
||||
private void startDataSourceProcessing(WizardDescriptor settings) {
|
||||
|
||||
logger.log(Level.INFO, "RAMAN startDataSourceProcessing()...");
|
||||
|
||||
// get the selected DSProcessor
|
||||
dsProcessor = dataSourcePanel.getComponent().GetCurrentDSProcessor();
|
||||
|
||||
|
||||
|
||||
// Add a cleanup task to interrupt the backgroud process if the
|
||||
// wizard exits while the background process is running.
|
||||
cleanupTask = addImageAction.new CleanupTask() {
|
||||
@Override
|
||||
void cleanup() throws Exception {
|
||||
cancelDataSourceProcessing();
|
||||
}
|
||||
};
|
||||
|
||||
// RAMAN TBD: this cleanup task needs to be cancelled, if dsProcessor runs successfully
|
||||
cleanupTask.enable();
|
||||
|
||||
DSPCallback cbObj = new DSPCallback () {
|
||||
@Override
|
||||
public void doneEDT(DSP_Result result, List<String> errList, List<Content> 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<String> errList, List<Content> 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<WizardDe
|
||||
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 = action.new CleanupTask() {
|
||||
AddImageAction.CleanupTask cancelledWhileRunning = addImageAction.new CleanupTask() {
|
||||
@Override
|
||||
void cleanup() throws Exception {
|
||||
logger.log(Level.INFO, "Add logical files process interrupted.");
|
||||
@ -474,7 +550,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
|
||||
// Add a cleanup task to interupt the backgroud process if the
|
||||
// wizard exits while the background process is running.
|
||||
AddImageAction.CleanupTask cancelledWhileRunning = action.new CleanupTask() {
|
||||
AddImageAction.CleanupTask cancelledWhileRunning = addImageAction.new CleanupTask() {
|
||||
@Override
|
||||
void cleanup() throws Exception {
|
||||
logger.log(Level.INFO, "Add image process interrupted.");
|
||||
@ -609,7 +685,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
// When everything happens without an error:
|
||||
|
||||
// the add-image process needs to be reverted if the wizard doesn't finish
|
||||
cleanupImage = action.new CleanupTask() {
|
||||
cleanupImage = addImageAction.new CleanupTask() {
|
||||
//note, CleanupTask runs inside EWT thread
|
||||
@Override
|
||||
void cleanup() throws Exception {
|
||||
|
@ -47,11 +47,16 @@ class AddImageWizardIterator implements WizardDescriptor.Iterator<WizardDescript
|
||||
*/
|
||||
private List<WizardDescriptor.Panel<WizardDescriptor>> getPanels() {
|
||||
if (panels == null) {
|
||||
AddImageWizardAddingProgressPanel wizPanel = new AddImageWizardAddingProgressPanel();
|
||||
panels = new ArrayList<WizardDescriptor.Panel<WizardDescriptor>>();
|
||||
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++) {
|
||||
|
@ -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<ContentTypePanel> registeredPanels = new ArrayList<ContentTypePanel>();;
|
||||
|
||||
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.
|
||||
|
42
Core/src/org/sleuthkit/autopsy/casemodule/DSPCallback.java
Normal file
42
Core/src/org/sleuthkit/autopsy/casemodule/DSPCallback.java
Normal file
@ -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<String> errList, List<Content> newContents)
|
||||
{
|
||||
|
||||
final DSP_Result resultf = result;
|
||||
final List<String> errListf = errList;
|
||||
final List<Content> 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<String> errList, List<Content> newContents);
|
||||
};
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2013 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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<Content> 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();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
566
Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java
Normal file
566
Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java
Normal file
@ -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<Content> getNewContents() {
|
||||
return addImageTask.getNewContents();
|
||||
}
|
||||
* *****/
|
||||
|
||||
|
||||
private static class CurrentDirectoryFetcher extends SwingWorker<Integer, Integer> {
|
||||
|
||||
//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<Integer, Integer> {
|
||||
|
||||
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<String> errorList = new ArrayList<String>();
|
||||
|
||||
private WizardDescriptor wizDescriptor;
|
||||
|
||||
private Logger logger = Logger.getLogger(AddImageTask.class.getName());
|
||||
private AddImageWizardAddingProgressPanel progressPanel;
|
||||
private DSPCallback callbackObj;
|
||||
|
||||
private final List<Content> newContents = Collections.synchronizedList(new ArrayList<Content>());
|
||||
|
||||
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<Content> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -158,8 +158,8 @@ public class ImageFilePanel extends ContentTypePanel implements DocumentListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentType getContentType() {
|
||||
return ContentType.IMAGE;
|
||||
public String getContentType() {
|
||||
return "IMAGE";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -153,8 +153,8 @@ public class LocalDiskPanel extends ContentTypePanel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentType getContentType() {
|
||||
return ContentType.DISK;
|
||||
public String getContentType() {
|
||||
return "DISK";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,8 +79,8 @@ public class LocalFilesPanel extends ContentTypePanel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentType getContentType() {
|
||||
return ContentType.LOCAL;
|
||||
public String getContentType() {
|
||||
return "LOCAL";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
x
Reference in New Issue
Block a user