From 0adee48f25056db78b89b32cbfac6c03c5f870cc Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Sun, 16 Nov 2014 00:01:34 -0500 Subject: [PATCH 1/3] Complete first draft of ingest job config refactor --- .../autopsy/ingest/Bundle.properties | 2 +- .../autopsy/ingest/Bundle_ja.properties | 2 +- .../ingest/IngestJobConfiguration.java | 378 ++++++++++++++++++ .../ingest/IngestJobConfigurationPanel.java | 36 +- .../autopsy/ingest/IngestJobConfigurator.java | 250 +----------- 5 files changed, 421 insertions(+), 247 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfiguration.java diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties index 1459a4604e..863b237cf7 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties @@ -64,7 +64,7 @@ IngestManager.StartIngestJobsTask.run.startupErr.dlgErrorList=\nErrors\: \n{0} IngestManager.StartIngestJobsTask.run.startupErr.dlgTitle=Ingest Failure IngestJobConfigurator.createModuleSettingsFolderForContext.exception.msg=Failed to create ingest module settings folder, cannot save settings. IngestJobConfigurator.createModuleSettingsFolderForContext.exception.title=Ingest Job Initialization Failure -IngestJobConfigurator.saveJobSettings.usermsg=Failed to save ingest job settings for {0} module. +IngestJobConfiguration.saveJobSettings.errmsg=Failed to save ingest job settings for {0} module. IngestJobConfigurator.saveJobSettings.usermsg.title=Ingest Job Settings IngestJobConfigurationPanel.descriptionLabel.text= IngestProgressSnapshotDialog.title.text=Ingest Progress Snapshot diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties index ba943a0b71..bec5ad1a2d 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties @@ -59,7 +59,7 @@ IngestManager.StartIngestJobsTask.run.startupErr.dlgSolution=\u5931\u6557\u3057\ IngestManager.StartIngestJobsTask.run.startupErr.dlgTitle=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5931\u6557 IngestJobConfigurator.createModuleSettingsFolderForContext.exception.msg=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u8a2d\u5b9a\u30d5\u30a9\u30eb\u30c0\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u8a2d\u5b9a\u3092\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3002 IngestJobConfigurator.createModuleSettingsFolderForContext.exception.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u521d\u671f\u5316\u306e\u5931\u6557 -IngestJobConfigurator.saveJobSettings.usermsg={0}\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a\u306e\u4fdd\u5b58\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +IngestJobConfiguration.saveJobSettings.errmsg={0}\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a\u306e\u4fdd\u5b58\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 IngestJobConfigurator.saveJobSettings.usermsg.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a IngestJob.progress.dataSourceIngest.initialDisplayName={0}\u3092\u89e3\u6790\u4e2d IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.dataSource=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9 diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfiguration.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfiguration.java new file mode 100644 index 0000000000..fdb7be6730 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfiguration.java @@ -0,0 +1,378 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 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.ingest; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.logging.Level; +import org.openide.util.NbBundle; +import org.openide.util.io.NbObjectInputStream; +import org.openide.util.io.NbObjectOutputStream; +import org.sleuthkit.autopsy.coreutils.ModuleSettings; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; +import org.sleuthkit.autopsy.coreutils.Logger; + +/** + * The ingest job configuration for a particular context. + */ +public class IngestJobConfiguration { + + private static final String ENABLED_INGEST_MODULES_KEY = "Enabled_Ingest_Modules"; //NON-NLS + private static final String DISABLED_INGEST_MODULES_KEY = "Disabled_Ingest_Modules"; //NON-NLS + private static final String PARSE_UNALLOC_SPACE_KEY = "Process_Unallocated_Space"; //NON-NLS + private static final String MODULE_SETTINGS_FOLDER = "IngestModuleSettings"; //NON-NLS + private static final String MODULE_SETTINGS_FOLDER_PATH = Paths.get(PlatformUtil.getUserConfigDirectory(), IngestJobConfiguration.MODULE_SETTINGS_FOLDER).toAbsolutePath().toString(); + private static final String MODULE_SETTINGS_FILE_EXT = ".settings"; //NON-NLS + private static final Logger logger = Logger.getLogger(IngestJobConfiguration.class.getName()); + private final String context; + private String moduleSettingsFolderForContext; + private final List moduleTemplates; + private boolean processUnallocatedSpace; + + /** + * A collection of warning and error messages generated by an ingest job + * configuration operation. + */ + public static class Messages { // RJCTODO: Improve name + + private final List errors; + private final List warnings; + + Messages() { + this.errors = new ArrayList<>(); + this.warnings = new ArrayList<>(); + } + + public List getWarningMessages() { + return Collections.unmodifiableList(this.warnings); + } + + public List getErrorMessages() { + return Collections.unmodifiableList(this.errors); + } + + } + + /** + * Constructs an empty ingest job configuration for a context. + * + * @param context The context identifier string. + */ + public IngestJobConfiguration(String context) { + this.context = context; + this.moduleTemplates = new ArrayList<>(); + this.processUnallocatedSpace = true; + } + + /** + * Loads the last saved configuration into memory, using a default + * configuration if a saved configuration does not exist. + * + * @return RJCTODO + */ + public Messages load() { + Messages messages = new Messages(); + this.read(messages); + return messages; + } + + /** + * Saves this ingest job configuration. + * + * @return RJCTODO + */ + public Messages save() { + Messages messages = new Messages(); + this.write(messages); + return messages; + } + + /** + * RJCTODO + * + * @return + */ + List getIngestModuleTemplates() { + return Collections.unmodifiableList(this.moduleTemplates); + } + + /** + * RJCTODO + * @param moduleTemplates + */ + void setIngestModuleTemplates(List moduleTemplates) { + this.moduleTemplates.clear(); + this.moduleTemplates.addAll(moduleTemplates); + } + + /** + * RJCTODO + * + * @return + */ + boolean shouldProcessUnallocatedSpace() { + return this.processUnallocatedSpace; + } + + /** + * RJCTODO + * @param processUnallocatedSpace + */ + void setProcessUnallocatedSpace(boolean processUnallocatedSpace) { + this.processUnallocatedSpace = processUnallocatedSpace; + } + + /** + * RJCTODO + * + * @return + */ + private void read(Messages messages) { + + // createModuleSettingsFolderForContext + try { + Path folder = Paths.get(IngestJobConfiguration.MODULE_SETTINGS_FOLDER_PATH, context); + Files.createDirectories(folder); + this.moduleSettingsFolderForContext = folder.toAbsolutePath().toString(); + } catch (Exception ex) { + // RJCTODO: + return; +// logger.log(Level.SEVERE, "Failed to create ingest module settings directory", ex); //NON-NLS +// JOptionPane.showMessageDialog(null, +// NbBundle.getMessage(this.getClass(), +// "IngestJobConfigurator.createModuleSettingsFolderForContext.exception.msg"), +// NbBundle.getMessage(this.getClass(), +// "IngestJobConfigurator.createModuleSettingsFolderForContext.exception.title"), +// JOptionPane.ERROR_MESSAGE); + } + + // Get the ingest module factories discovered by the ingest module + // loader. + List moduleFactories = IngestModuleFactoryLoader.getIngestModuleFactories(); + HashSet loadedModuleNames = new HashSet<>(); + for (IngestModuleFactory moduleFactory : moduleFactories) { + loadedModuleNames.add(moduleFactory.getModuleDisplayName()); + } + + // Get the enabled and disabled ingest modules settings for the current + // context. Observe that the default settings make all loaded ingest + // modules enabled. + HashSet enabledModuleNames = getModulesNamesFromSetting(IngestJobConfiguration.ENABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(loadedModuleNames)); + HashSet disabledModuleNames = getModulesNamesFromSetting(IngestJobConfiguration.DISABLED_INGEST_MODULES_KEY, ""); + + // Check for missing modules. + List missingModuleNames = new ArrayList<>(); + for (String moduleName : enabledModuleNames) { + if (!loadedModuleNames.contains(moduleName)) { + missingModuleNames.add(moduleName); + } + } + for (String moduleName : disabledModuleNames) { + if (!loadedModuleNames.contains(moduleName)) { + missingModuleNames.add(moduleName); + } + } + for (String moduleName : missingModuleNames) { + enabledModuleNames.remove(moduleName); + disabledModuleNames.remove(moduleName); + messages.warnings.add(String.format("Previously loaded %s module could not be found", moduleName)); //NON-NLS + } + + // Create ingest module templates. + for (IngestModuleFactory moduleFactory : moduleFactories) { + IngestModuleTemplate moduleTemplate = new IngestModuleTemplate(moduleFactory, loadJobSettings(moduleFactory)); + String moduleName = moduleTemplate.getModuleName(); + if (enabledModuleNames.contains(moduleName)) { + moduleTemplate.setEnabled(true); + } else if (disabledModuleNames.contains(moduleName)) { + moduleTemplate.setEnabled(false); + } else { + // The module factory was loaded, but the module name does not + // appear in the enabled/disabled module settings. Treat the + // module as a new module and enable it by default. + moduleTemplate.setEnabled(true); + enabledModuleNames.add(moduleName); + } + this.moduleTemplates.add(moduleTemplate); + } + + // Update the enabled/disabled ingest module settings to reflect any + // missing modules or newly discovered modules. + ModuleSettings.setConfigSetting(this.context, ENABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(enabledModuleNames)); + ModuleSettings.setConfigSetting(this.context, DISABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(disabledModuleNames)); + + // Get the process unallocated space flag setting. If the setting does + // not exist yet, default it to true. + if (ModuleSettings.settingExists(this.context, PARSE_UNALLOC_SPACE_KEY) == false) { + ModuleSettings.setConfigSetting(this.context, PARSE_UNALLOC_SPACE_KEY, "true"); //NON-NLS + } + this.processUnallocatedSpace = Boolean.parseBoolean(ModuleSettings.getConfigSetting(this.context, PARSE_UNALLOC_SPACE_KEY)); + } + + /** + * RJCTODO + * + * @param key + * @param defaultSetting + * @return + */ + private HashSet getModulesNamesFromSetting(String key, String defaultSetting) { + // Get the ingest modules setting from the user's config file. + // If there is no such setting yet, create the default setting. + if (ModuleSettings.settingExists(this.context, key) == false) { + ModuleSettings.setConfigSetting(this.context, key, defaultSetting); + } + HashSet moduleNames = new HashSet<>(); + String modulesSetting = ModuleSettings.getConfigSetting(this.context, key); + if (!modulesSetting.isEmpty()) { + String[] settingNames = modulesSetting.split(", "); + for (String name : settingNames) { + // Map some old core module names to the current core module names. + switch (name) { + case "Thunderbird Parser": //NON-NLS + case "MBox Parser": //NON-NLS + moduleNames.add("Email Parser"); //NON-NLS + break; + case "File Extension Mismatch Detection": //NON-NLS + moduleNames.add("Extension Mismatch Detector"); //NON-NLS + break; + case "EWF Verify": //NON-NLS + case "E01 Verify": //NON-NLS + moduleNames.add("E01 Verifier"); //NON-NLS + break; + default: + moduleNames.add(name); + } + } + } + return moduleNames; + } + + /** + * RJCTODO + * + * @param factory + * @return + */ + private IngestModuleIngestJobSettings loadJobSettings(IngestModuleFactory factory) { + IngestModuleIngestJobSettings settings = null; + File settingsFile = new File(getModuleSettingsFilePath(factory)); + if (settingsFile.exists()) { + try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(settingsFile.getAbsolutePath()))) { + settings = (IngestModuleIngestJobSettings) in.readObject(); + } catch (IOException | ClassNotFoundException ex) { + String logMessage = String.format("Error loading ingest job settings for %s module for %s context, using defaults", factory.getModuleDisplayName(), this.context); //NON-NLS +// logger.log(Level.WARNING, logMessage, ex); RJCTODO + } + } + if (settings == null) { + settings = factory.getDefaultIngestJobSettings(); + } + return settings; + } + + /** + * RJCTODO + * @param factory + * @return + */ + private String getModuleSettingsFilePath(IngestModuleFactory factory) { + StringBuilder filePath = new StringBuilder(this.moduleSettingsFolderForContext); + filePath.append(File.separator); + filePath.append(factory.getClass().getCanonicalName()); + filePath.append(MODULE_SETTINGS_FILE_EXT); + return filePath.toString(); + } + + /** + * RJCTODO + * @param messages + */ + private void write(Messages messages) { + // Save the enabled/disabled ingest module settings for the current context. + HashSet enabledModuleNames = new HashSet<>(); + HashSet disabledModuleNames = new HashSet<>(); + for (IngestModuleTemplate moduleTemplate : moduleTemplates) { + saveModuleSettings(moduleTemplate.getModuleFactory(), moduleTemplate.getModuleSettings(), messages); + String moduleName = moduleTemplate.getModuleName(); + if (moduleTemplate.isEnabled()) { + enabledModuleNames.add(moduleName); + } else { + disabledModuleNames.add(moduleName); + } + } + ModuleSettings.setConfigSetting(this.context, ENABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(enabledModuleNames)); + ModuleSettings.setConfigSetting(this.context, DISABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(disabledModuleNames)); + + // Save the process unallocated space setting for the current context. + String processUnalloc = Boolean.toString(this.processUnallocatedSpace); + ModuleSettings.setConfigSetting(this.context, PARSE_UNALLOC_SPACE_KEY, processUnalloc); + } + + /** + * Serializes the ingest job settings for an ingest module for this context. + * + * @param factory The ingest module factory for the ingest module. + * @param settings The ingest job settings for the ingest module + * @param messages A collection of error and warning messages to receive any + * error messages generated. + */ + private void saveModuleSettings(IngestModuleFactory factory, IngestModuleIngestJobSettings settings, Messages messages) { + try { + try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(getModuleSettingsFilePath(factory)))) { + out.writeObject(settings); + } + } catch (IOException ex) { + logger.log(Level.SEVERE, String.format("Error saving ingest job settings for %s ingest module for %s context", factory.getModuleDisplayName(), this.context), ex); //NON-NLS + messages.errors.add(NbBundle.getMessage(this.getClass(), "IngestJobConfiguration.saveJobSettings.errmsg", factory.getModuleDisplayName())); + } + } + + /** + * RJCTODO: Consider making this a generally available utility; there might + * be a cleaner impl in Core Java 2 + * + * @param input + * @return + */ + private static String makeCommaSeparatedList(HashSet input) { + if (input == null || input.isEmpty()) { + return ""; + } + + ArrayList list = new ArrayList<>(); + list.addAll(input); + StringBuilder csvList = new StringBuilder(); + for (int i = 0; i < list.size() - 1; ++i) { + csvList.append(list.get(i)).append(", "); + } + csvList.append(list.get(list.size() - 1)); + return csvList.toString(); + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurationPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurationPanel.java index 732f27522c..d72b1bd973 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurationPanel.java @@ -40,20 +40,25 @@ import org.sleuthkit.autopsy.corecomponents.AdvancedConfigurationDialog; */ class IngestJobConfigurationPanel extends javax.swing.JPanel { - private List modules = new ArrayList<>(); - private boolean processUnallocatedSpace = false; - private IngestModuleModel selectedModule = null; + private final IngestJobConfiguration config; + private final List modules; + private IngestModuleModel selectedModule; - IngestJobConfigurationPanel(List moduleTemplates, boolean processUnallocatedSpace) { - for (IngestModuleTemplate moduleTemplate : moduleTemplates) { - modules.add(new IngestModuleModel(moduleTemplate)); - } - this.processUnallocatedSpace = processUnallocatedSpace; + IngestJobConfigurationPanel(IngestJobConfiguration config) { + this.config = config; + this.modules = new ArrayList<>(); + for (IngestModuleTemplate moduleTemplate : config.getIngestModuleTemplates()) { + this.modules.add(new IngestModuleModel(moduleTemplate)); + } initComponents(); customizeComponents(); } - - List getIngestModuleTemplates() { + + /** + * RJCTODO + * @return + */ + IngestJobConfiguration getConfig() { List moduleTemplates = new ArrayList<>(); for (IngestModuleModel module : modules) { IngestModuleTemplate moduleTemplate = module.getIngestModuleTemplate(); @@ -63,11 +68,8 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel { } moduleTemplates.add(moduleTemplate); } - return moduleTemplates; - } - - boolean getProcessUnallocSpace() { - return processUnallocCheckbox.isSelected(); + this.config.setIngestModuleTemplates(moduleTemplates); + return this.config; } private void customizeComponents() { @@ -113,7 +115,7 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel { } }); - processUnallocCheckbox.setSelected(processUnallocatedSpace); + processUnallocCheckbox.setSelected(this.config.shouldProcessUnallocatedSpace()); } /** @@ -261,7 +263,7 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel { }// //GEN-END:initComponents private void processUnallocCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_processUnallocCheckboxActionPerformed - processUnallocatedSpace = processUnallocCheckbox.isSelected(); + this.config.setProcessUnallocatedSpace(processUnallocCheckbox.isSelected()); }//GEN-LAST:event_processUnallocCheckboxActionPerformed private void advancedButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_advancedButtonActionPerformed diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurator.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurator.java index f9aaf17aef..e4eec50ee1 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurator.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurator.java @@ -18,216 +18,37 @@ */ package org.sleuthkit.autopsy.ingest; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.file.Files; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.logging.Level; -import javax.swing.JOptionPane; import javax.swing.JPanel; - -import org.openide.util.NbBundle; -import org.openide.util.io.NbObjectInputStream; -import org.openide.util.io.NbObjectOutputStream; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.ModuleSettings; -import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.datamodel.Content; /** * Provides a mechanism for creating and persisting an ingest job configuration * for a particular context and for launching ingest jobs that process one or * more data sources using the ingest job configuration. + * + * @deprecated Use the IngestModuleConfiguration and IngestJobConfigurationPanel + * and IngestManager.startIngestJob() or IngestManager.startIngestJobNoUI() instead. // RJCTODO */ +@Deprecated public final class IngestJobConfigurator { - private static final String ENABLED_INGEST_MODULES_KEY = "Enabled_Ingest_Modules"; //NON-NLS - private static final String DISABLED_INGEST_MODULES_KEY = "Disabled_Ingest_Modules"; //NON-NLS - private static final String PARSE_UNALLOC_SPACE_KEY = "Process_Unallocated_Space"; //NON-NLS - private static final String MODULE_SETTINGS_FOLDER_PATH = new StringBuilder(PlatformUtil.getUserConfigDirectory()).append(File.separator).append("IngestModuleSettings").toString(); //NON-NLS - private static final String MODULE_SETTINGS_FILE_EXT = ".settings"; //NON-NLS - private static final Logger logger = Logger.getLogger(IngestJobConfigurator.class.getName()); - private final String launcherContext; - private String moduleSettingsFolderForContext = null; - private final List warnings = new ArrayList<>(); - private IngestJobConfigurationPanel ingestConfigPanel = null; + private final IngestJobConfiguration config; + private final IngestJobConfigurationPanel ingestConfigPanel; + private IngestJobConfiguration.Messages messages; /** * Constructs an ingest job launcher that creates and persists an ingest job * configuration for a particular context and launches ingest jobs that * process one or more data sources using the ingest job configuration. * - * @param launcherContext The context identifier. + * @param context The context identifier. */ - public IngestJobConfigurator(String launcherContext) { - this.launcherContext = launcherContext; - - createModuleSettingsFolderForContext(); - - // Get the ingest module factories discovered by the ingest module - // loader. - List moduleFactories = IngestModuleFactoryLoader.getIngestModuleFactories(); - HashSet loadedModuleNames = new HashSet<>(); - for (IngestModuleFactory moduleFactory : moduleFactories) { - loadedModuleNames.add(moduleFactory.getModuleDisplayName()); - } - - // Get the enabled and disabled ingest modules settings for the current - // context. Observe that the default settings make all loaded ingest - // modules enabled. - HashSet enabledModuleNames = getModulesNamesFromSetting(ENABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(loadedModuleNames)); - HashSet disabledModuleNames = getModulesNamesFromSetting(DISABLED_INGEST_MODULES_KEY, ""); - - // Check for missing modules. - List missingModuleNames = new ArrayList<>(); - for (String moduleName : enabledModuleNames) { - if (!loadedModuleNames.contains(moduleName)) { - missingModuleNames.add(moduleName); - } - } - for (String moduleName : disabledModuleNames) { - if (!loadedModuleNames.contains(moduleName)) { - missingModuleNames.add(moduleName); - } - } - for (String moduleName : missingModuleNames) { - enabledModuleNames.remove(moduleName); - disabledModuleNames.remove(moduleName); - warnings.add(String.format("Previously loaded %s module could not be found", moduleName)); //NON-NLS - } - - // Create ingest module templates. - List moduleTemplates = new ArrayList<>(); - for (IngestModuleFactory moduleFactory : moduleFactories) { - IngestModuleTemplate moduleTemplate = new IngestModuleTemplate(moduleFactory, loadJobSettings(moduleFactory)); - String moduleName = moduleTemplate.getModuleName(); - if (enabledModuleNames.contains(moduleName)) { - moduleTemplate.setEnabled(true); - } else if (disabledModuleNames.contains(moduleName)) { - moduleTemplate.setEnabled(false); - } else { - // The module factory was loaded, but the module name does not - // appear in the enabled/disabled module settings. Treat the - // module as a new module and enable it by default. - moduleTemplate.setEnabled(true); - enabledModuleNames.add(moduleName); - } - moduleTemplates.add(moduleTemplate); - } - - // Update the enabled/disabled ingest module settings to reflect any - // missing modules or newly discovered modules. - ModuleSettings.setConfigSetting(launcherContext, ENABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(enabledModuleNames)); - ModuleSettings.setConfigSetting(launcherContext, DISABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(disabledModuleNames)); - - // Get the process unallocated space flag setting. If the setting does - // not exist yet, default it to true. - if (ModuleSettings.settingExists(launcherContext, PARSE_UNALLOC_SPACE_KEY) == false) { - ModuleSettings.setConfigSetting(launcherContext, PARSE_UNALLOC_SPACE_KEY, "true"); //NON-NLS - } - boolean processUnallocatedSpace = Boolean.parseBoolean(ModuleSettings.getConfigSetting(launcherContext, PARSE_UNALLOC_SPACE_KEY)); - - // Make the configuration panel for the context. - ingestConfigPanel = new IngestJobConfigurationPanel(moduleTemplates, processUnallocatedSpace); - } - - private void createModuleSettingsFolderForContext() { - try { - StringBuilder folderPath = new StringBuilder(MODULE_SETTINGS_FOLDER_PATH); - folderPath.append(File.separator); - folderPath.append(launcherContext); - folderPath.append(File.separator); - File folder = new File(folderPath.toString()); - if (!folder.exists()) { - Files.createDirectories(folder.toPath()); - } - moduleSettingsFolderForContext = folder.getAbsolutePath(); - } catch (Exception ex) { - logger.log(Level.SEVERE, "Failed to create ingest module settings directory", ex); //NON-NLS - JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), - "IngestJobConfigurator.createModuleSettingsFolderForContext.exception.msg"), - NbBundle.getMessage(this.getClass(), - "IngestJobConfigurator.createModuleSettingsFolderForContext.exception.title"), - JOptionPane.ERROR_MESSAGE); - } - } - - private HashSet getModulesNamesFromSetting(String key, String defaultSetting) { - // Get the ingest modules setting from the user's config file. - // If there is no such setting yet, create the default setting. - if (ModuleSettings.settingExists(launcherContext, key) == false) { - ModuleSettings.setConfigSetting(launcherContext, key, defaultSetting); - } - HashSet moduleNames = new HashSet<>(); - String modulesSetting = ModuleSettings.getConfigSetting(launcherContext, key); - if (!modulesSetting.isEmpty()) { - String[] settingNames = modulesSetting.split(", "); - for (String name : settingNames) { - // Map some old core module names to the current core module names. - switch (name) { - case "Thunderbird Parser": //NON-NLS - case "MBox Parser": //NON-NLS - moduleNames.add("Email Parser"); //NON-NLS - break; - case "File Extension Mismatch Detection": //NON-NLS - moduleNames.add("Extension Mismatch Detector"); //NON-NLS - break; - case "EWF Verify": //NON-NLS - case "E01 Verify": //NON-NLS - moduleNames.add("E01 Verifier"); //NON-NLS - break; - default: - moduleNames.add(name); - } - } - } - return moduleNames; - } - - private IngestModuleIngestJobSettings loadJobSettings(IngestModuleFactory factory) { - IngestModuleIngestJobSettings settings = null; - File settingsFile = new File(getModuleSettingsFilePath(factory)); - if (settingsFile.exists()) { - try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(settingsFile.getAbsolutePath()))) { - settings = (IngestModuleIngestJobSettings) in.readObject(); - } catch (IOException | ClassNotFoundException ex) { - String logMessage = String.format("Error loading ingest job settings for %s module for %s context, using defaults", factory.getModuleDisplayName(), launcherContext); //NON-NLS - logger.log(Level.WARNING, logMessage, ex); - } - } - if (settings == null) { - settings = factory.getDefaultIngestJobSettings(); - } - return settings; - } - - private void saveJobSettings(IngestModuleFactory factory, IngestModuleIngestJobSettings settings) { - try { - try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(getModuleSettingsFilePath(factory)))) { - out.writeObject(settings); - } - } catch (IOException ex) { - String logMessage = String.format("Error saving ingest job settings for %s module for %s context", factory.getModuleDisplayName(), launcherContext); //NON-NLS - logger.log(Level.SEVERE, logMessage, ex); - String userMessage = NbBundle.getMessage(this.getClass(), "IngestJobConfigurator.saveJobSettings.usermsg", factory.getModuleDisplayName()); - JOptionPane.showMessageDialog(null, userMessage, - NbBundle.getMessage(this.getClass(), - "IngestJobConfigurator.saveJobSettings.usermsg.title"), - JOptionPane.WARNING_MESSAGE); - } - } - - private String getModuleSettingsFilePath(IngestModuleFactory factory) { - StringBuilder filePath = new StringBuilder(this.moduleSettingsFolderForContext); - filePath.append(File.separator); - filePath.append(factory.getClass().getCanonicalName()); - filePath.append(MODULE_SETTINGS_FILE_EXT); - return filePath.toString(); + @Deprecated + public IngestJobConfigurator(String context) { + this.config = new IngestJobConfiguration(context); + this.ingestConfigPanel = new IngestJobConfigurationPanel(config); } /** @@ -236,7 +57,11 @@ public final class IngestJobConfigurator { * * @return A collection of warning messages. */ + @Deprecated public List getIngestJobConfigWarnings() { + List warnings = new ArrayList<>(); + warnings.addAll(this.messages.getWarningMessages()); + warnings.addAll(this.messages.getErrorMessages()); return warnings; } @@ -247,6 +72,7 @@ public final class IngestJobConfigurator { * @return A JPanel with components that can be used to create an ingest job * configuration. */ + @Deprecated public JPanel getIngestJobConfigPanel() { return ingestConfigPanel; } @@ -254,42 +80,9 @@ public final class IngestJobConfigurator { /** * Persists the ingest job configuration for the specified context. */ + @Deprecated public void saveIngestJobConfig() { - List moduleTemplates = ingestConfigPanel.getIngestModuleTemplates(); - - // Save the enabled/disabled ingest module settings for the current context. - HashSet enabledModuleNames = new HashSet<>(); - HashSet disabledModuleNames = new HashSet<>(); - for (IngestModuleTemplate moduleTemplate : moduleTemplates) { - saveJobSettings(moduleTemplate.getModuleFactory(), moduleTemplate.getModuleSettings()); - String moduleName = moduleTemplate.getModuleName(); - if (moduleTemplate.isEnabled()) { - enabledModuleNames.add(moduleName); - } else { - disabledModuleNames.add(moduleName); - } - } - ModuleSettings.setConfigSetting(launcherContext, ENABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(enabledModuleNames)); - ModuleSettings.setConfigSetting(launcherContext, DISABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(disabledModuleNames)); - - // Save the process unallocated space setting for the current context. - String processUnalloc = Boolean.toString(ingestConfigPanel.getProcessUnallocSpace()); - ModuleSettings.setConfigSetting(launcherContext, PARSE_UNALLOC_SPACE_KEY, processUnalloc); - } - - private static String makeCommaSeparatedList(HashSet input) { - if (input == null || input.isEmpty()) { - return ""; - } - - ArrayList list = new ArrayList<>(); - list.addAll(input); - StringBuilder csvList = new StringBuilder(); - for (int i = 0; i < list.size() - 1; ++i) { - csvList.append(list.get(i)).append(", "); - } - csvList.append(list.get(list.size() - 1)); - return csvList.toString(); + this.messages = this.config.save(); } /** @@ -298,10 +91,11 @@ public final class IngestJobConfigurator { * * @param dataSources The data sources to ingest. */ + @Deprecated public void startIngestJobs(List dataSources) { // Filter out the disabled ingest module templates. List enabledModuleTemplates = new ArrayList<>(); - List moduleTemplates = ingestConfigPanel.getIngestModuleTemplates(); + List moduleTemplates = this.config.getIngestModuleTemplates(); for (IngestModuleTemplate moduleTemplate : moduleTemplates) { if (moduleTemplate.isEnabled()) { enabledModuleTemplates.add(moduleTemplate); @@ -309,7 +103,7 @@ public final class IngestJobConfigurator { } if ((!enabledModuleTemplates.isEmpty()) && (dataSources != null) && (!dataSources.isEmpty())) { - IngestManager.getInstance().startIngestJobs(dataSources, enabledModuleTemplates, ingestConfigPanel.getProcessUnallocSpace()); + IngestManager.getInstance().startIngestJobs(dataSources, enabledModuleTemplates, this.config.shouldProcessUnallocatedSpace()); } } } From 5407d00bd50de268195f14a50caeacc079fe1108 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Sun, 16 Nov 2014 08:30:44 -0500 Subject: [PATCH 2/3] Continue refactoring of ingest job configuration --- .../autopsy/ingest/Bundle.properties | 6 +- .../ingest/IngestJobConfigurationPanel.java | 8 +- .../autopsy/ingest/IngestJobConfigurator.java | 21 +- ...figuration.java => IngestJobSettings.java} | 206 +++++++++--------- 4 files changed, 117 insertions(+), 124 deletions(-) rename Core/src/org/sleuthkit/autopsy/ingest/{IngestJobConfiguration.java => IngestJobSettings.java} (69%) diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties index 863b237cf7..09fe829713 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties @@ -62,9 +62,11 @@ IngestManager.StartIngestJobsTask.run.startupErr.dlgMsg=Unable to start up one o IngestManager.StartIngestJobsTask.run.startupErr.dlgSolution=Please disable the failed modules or fix the errors and then restart ingest \nby right clicking on the data source and selecting Run Ingest Modules. IngestManager.StartIngestJobsTask.run.startupErr.dlgErrorList=\nErrors\: \n{0} IngestManager.StartIngestJobsTask.run.startupErr.dlgTitle=Ingest Failure -IngestJobConfigurator.createModuleSettingsFolderForContext.exception.msg=Failed to create ingest module settings folder, cannot save settings. -IngestJobConfigurator.createModuleSettingsFolderForContext.exception.title=Ingest Job Initialization Failure +IngestJobConfiguration.createModuleSettingsFolderForContext.exception.msg=Failed to create ingest module settings folder, cannot save settings. +IngestJobConfiguration.missingModule.warning=Previously loaded {0} module could not be found. IngestJobConfiguration.saveJobSettings.errmsg=Failed to save ingest job settings for {0} module. + +IngestJobConfigurator.createModuleSettingsFolderForContext.exception.title=Ingest Job Initialization Failure IngestJobConfigurator.saveJobSettings.usermsg.title=Ingest Job Settings IngestJobConfigurationPanel.descriptionLabel.text= IngestProgressSnapshotDialog.title.text=Ingest Progress Snapshot diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurationPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurationPanel.java index d72b1bd973..06756f972b 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurationPanel.java @@ -40,11 +40,11 @@ import org.sleuthkit.autopsy.corecomponents.AdvancedConfigurationDialog; */ class IngestJobConfigurationPanel extends javax.swing.JPanel { - private final IngestJobConfiguration config; + private final IngestJobSettings config; private final List modules; private IngestModuleModel selectedModule; - IngestJobConfigurationPanel(IngestJobConfiguration config) { + IngestJobConfigurationPanel(IngestJobSettings config) { this.config = config; this.modules = new ArrayList<>(); for (IngestModuleTemplate moduleTemplate : config.getIngestModuleTemplates()) { @@ -58,7 +58,7 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel { * RJCTODO * @return */ - IngestJobConfiguration getConfig() { + IngestJobSettings getConfig() { List moduleTemplates = new ArrayList<>(); for (IngestModuleModel module : modules) { IngestModuleTemplate moduleTemplate = module.getIngestModuleTemplate(); @@ -115,7 +115,7 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel { } }); - processUnallocCheckbox.setSelected(this.config.shouldProcessUnallocatedSpace()); + processUnallocCheckbox.setSelected(this.config.getProcessUnallocatedSpace()); } /** diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurator.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurator.java index e4eec50ee1..22dc882b31 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurator.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurator.java @@ -29,14 +29,14 @@ import org.sleuthkit.datamodel.Content; * more data sources using the ingest job configuration. * * @deprecated Use the IngestModuleConfiguration and IngestJobConfigurationPanel - * and IngestManager.startIngestJob() or IngestManager.startIngestJobNoUI() instead. // RJCTODO + * and IngestManager.startIngestJob() or IngestManager.startIngestJobNoUI() + * instead. // RJCTODO */ @Deprecated public final class IngestJobConfigurator { - private final IngestJobConfiguration config; + private final IngestJobSettings settings; private final IngestJobConfigurationPanel ingestConfigPanel; - private IngestJobConfiguration.Messages messages; /** * Constructs an ingest job launcher that creates and persists an ingest job @@ -47,8 +47,8 @@ public final class IngestJobConfigurator { */ @Deprecated public IngestJobConfigurator(String context) { - this.config = new IngestJobConfiguration(context); - this.ingestConfigPanel = new IngestJobConfigurationPanel(config); + this.settings = new IngestJobSettings(context); + this.ingestConfigPanel = new IngestJobConfigurationPanel(settings); } /** @@ -59,10 +59,7 @@ public final class IngestJobConfigurator { */ @Deprecated public List getIngestJobConfigWarnings() { - List warnings = new ArrayList<>(); - warnings.addAll(this.messages.getWarningMessages()); - warnings.addAll(this.messages.getErrorMessages()); - return warnings; + return this.settings.getWarnings(); } /** @@ -82,7 +79,7 @@ public final class IngestJobConfigurator { */ @Deprecated public void saveIngestJobConfig() { - this.messages = this.config.save(); + this.settings.save(); } /** @@ -95,7 +92,7 @@ public final class IngestJobConfigurator { public void startIngestJobs(List dataSources) { // Filter out the disabled ingest module templates. List enabledModuleTemplates = new ArrayList<>(); - List moduleTemplates = this.config.getIngestModuleTemplates(); + List moduleTemplates = this.settings.getIngestModuleTemplates(); for (IngestModuleTemplate moduleTemplate : moduleTemplates) { if (moduleTemplate.isEnabled()) { enabledModuleTemplates.add(moduleTemplate); @@ -103,7 +100,7 @@ public final class IngestJobConfigurator { } if ((!enabledModuleTemplates.isEmpty()) && (dataSources != null) && (!dataSources.isEmpty())) { - IngestManager.getInstance().startIngestJobs(dataSources, enabledModuleTemplates, this.config.shouldProcessUnallocatedSpace()); + IngestManager.getInstance().startIngestJobs(dataSources, enabledModuleTemplates, this.settings.getProcessUnallocatedSpace()); } } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfiguration.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java similarity index 69% rename from Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfiguration.java rename to Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java index fdb7be6730..34486b762d 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfiguration.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java @@ -38,154 +38,142 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.Logger; /** - * The ingest job configuration for a particular context. + * The ingest job settings for a particular context. */ -public class IngestJobConfiguration { +public class IngestJobSettings { private static final String ENABLED_INGEST_MODULES_KEY = "Enabled_Ingest_Modules"; //NON-NLS private static final String DISABLED_INGEST_MODULES_KEY = "Disabled_Ingest_Modules"; //NON-NLS private static final String PARSE_UNALLOC_SPACE_KEY = "Process_Unallocated_Space"; //NON-NLS private static final String MODULE_SETTINGS_FOLDER = "IngestModuleSettings"; //NON-NLS - private static final String MODULE_SETTINGS_FOLDER_PATH = Paths.get(PlatformUtil.getUserConfigDirectory(), IngestJobConfiguration.MODULE_SETTINGS_FOLDER).toAbsolutePath().toString(); + private static final String MODULE_SETTINGS_FOLDER_PATH = Paths.get(PlatformUtil.getUserConfigDirectory(), IngestJobSettings.MODULE_SETTINGS_FOLDER).toAbsolutePath().toString(); private static final String MODULE_SETTINGS_FILE_EXT = ".settings"; //NON-NLS - private static final Logger logger = Logger.getLogger(IngestJobConfiguration.class.getName()); + private static final String PROCESS_UNALLOC_SPACE_DEFAULT = "true"; + private static final Logger logger = Logger.getLogger(IngestJobSettings.class.getName()); private final String context; - private String moduleSettingsFolderForContext; + private String moduleSettingsFolderPath; private final List moduleTemplates; private boolean processUnallocatedSpace; + private final List warnings; /** - * A collection of warning and error messages generated by an ingest job - * configuration operation. - */ - public static class Messages { // RJCTODO: Improve name - - private final List errors; - private final List warnings; - - Messages() { - this.errors = new ArrayList<>(); - this.warnings = new ArrayList<>(); - } - - public List getWarningMessages() { - return Collections.unmodifiableList(this.warnings); - } - - public List getErrorMessages() { - return Collections.unmodifiableList(this.errors); - } - - } - - /** - * Constructs an empty ingest job configuration for a context. + * Constructs an ingest job settings object for a given context. * * @param context The context identifier string. */ - public IngestJobConfiguration(String context) { + public IngestJobSettings(String context) { this.context = context; this.moduleTemplates = new ArrayList<>(); - this.processUnallocatedSpace = true; + this.processUnallocatedSpace = Boolean.parseBoolean(IngestJobSettings.PROCESS_UNALLOC_SPACE_DEFAULT); + this.warnings = new ArrayList<>(); + this.createSavedModuleSettingsFolder(); + this.load(); } /** - * Loads the last saved configuration into memory, using a default - * configuration if a saved configuration does not exist. - * - * @return RJCTODO + * Saves the ingest job settings for this context. */ - public Messages load() { - Messages messages = new Messages(); - this.read(messages); - return messages; + public void save() { + this.store(); } /** - * Saves this ingest job configuration. + * Gets and clears any warnings associated with the ingest job settings for + * this context. * - * @return RJCTODO + * @return A collection of warning messages, possibly empty. */ - public Messages save() { - Messages messages = new Messages(); - this.write(messages); - return messages; + public List getWarnings() { + List warningMessages = new ArrayList<>(this.warnings); + this.warnings.clear(); + return warningMessages; } /** - * RJCTODO + * Gets the ingest module templates for this context. * - * @return + * @return A list of the ingest module templates. */ List getIngestModuleTemplates() { return Collections.unmodifiableList(this.moduleTemplates); } /** - * RJCTODO - * @param moduleTemplates + * Sets the ingest module templates for this context. + * + * @param moduleTemplates The list of ingest module templates. */ void setIngestModuleTemplates(List moduleTemplates) { this.moduleTemplates.clear(); - this.moduleTemplates.addAll(moduleTemplates); + this.moduleTemplates.addAll(moduleTemplates); } - + /** - * RJCTODO + * Gets the process unallocated space flag for this context. * - * @return + * @return True or false. */ - boolean shouldProcessUnallocatedSpace() { + boolean getProcessUnallocatedSpace() { return this.processUnallocatedSpace; } /** - * RJCTODO - * @param processUnallocatedSpace + * Sets the process unallocated space flag for this context. + * + * @param processUnallocatedSpace True or false. */ void setProcessUnallocatedSpace(boolean processUnallocatedSpace) { this.processUnallocatedSpace = processUnallocatedSpace; } - - /** - * RJCTODO - * - * @return - */ - private void read(Messages messages) { - // createModuleSettingsFolderForContext + /** + * Creates the folder for saving individual ingest module settings for this + * context, if it does not already exist. + */ + private void createSavedModuleSettingsFolder() { try { - Path folder = Paths.get(IngestJobConfiguration.MODULE_SETTINGS_FOLDER_PATH, context); + Path folder = Paths.get(IngestJobSettings.MODULE_SETTINGS_FOLDER_PATH, context); Files.createDirectories(folder); - this.moduleSettingsFolderForContext = folder.toAbsolutePath().toString(); - } catch (Exception ex) { - // RJCTODO: - return; -// logger.log(Level.SEVERE, "Failed to create ingest module settings directory", ex); //NON-NLS + this.moduleSettingsFolderPath = folder.toAbsolutePath().toString(); + } catch (IOException ex) { + logger.log(Level.SEVERE, "Failed to create ingest module settings directory", ex); //NON-NLS + this.warnings.add(NbBundle.getMessage(IngestJobSettings.class, "IngestJobConfiguration.createModuleSettingsFolderForContext.exception.msg")); //NON-NLS + + // RJCTODO: Add this sort of code to clients, move bundle property to clients // JOptionPane.showMessageDialog(null, // NbBundle.getMessage(this.getClass(), -// "IngestJobConfigurator.createModuleSettingsFolderForContext.exception.msg"), +// "IngestJobConfiguration.createModuleSettingsFolderForContext.exception.msg"), // NbBundle.getMessage(this.getClass(), // "IngestJobConfigurator.createModuleSettingsFolderForContext.exception.title"), // JOptionPane.ERROR_MESSAGE); } + } - // Get the ingest module factories discovered by the ingest module - // loader. + /** + * Loads the saved or default ingest job settings for this context into + * memory. + */ + private void load() { + /** + * Get the ingest module factories discovered by the ingest module + * loader. + */ List moduleFactories = IngestModuleFactoryLoader.getIngestModuleFactories(); HashSet loadedModuleNames = new HashSet<>(); for (IngestModuleFactory moduleFactory : moduleFactories) { loadedModuleNames.add(moduleFactory.getModuleDisplayName()); } - // Get the enabled and disabled ingest modules settings for the current - // context. Observe that the default settings make all loaded ingest - // modules enabled. - HashSet enabledModuleNames = getModulesNamesFromSetting(IngestJobConfiguration.ENABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(loadedModuleNames)); - HashSet disabledModuleNames = getModulesNamesFromSetting(IngestJobConfiguration.DISABLED_INGEST_MODULES_KEY, ""); + /** + * Get the enabled/disabled ingest modules settings for this context. By + * default, all loaded modules are enabled. + */ + HashSet enabledModuleNames = getModulesNamesFromSetting(IngestJobSettings.ENABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(loadedModuleNames)); + HashSet disabledModuleNames = getModulesNamesFromSetting(IngestJobSettings.DISABLED_INGEST_MODULES_KEY, ""); //NON-NLS - // Check for missing modules. + /** + * Check for missing modules and create warnings if any are found. + */ List missingModuleNames = new ArrayList<>(); for (String moduleName : enabledModuleNames) { if (!loadedModuleNames.contains(moduleName)) { @@ -200,12 +188,15 @@ public class IngestJobConfiguration { for (String moduleName : missingModuleNames) { enabledModuleNames.remove(moduleName); disabledModuleNames.remove(moduleName); - messages.warnings.add(String.format("Previously loaded %s module could not be found", moduleName)); //NON-NLS + this.warnings.add(NbBundle.getMessage(IngestJobSettings.class, "IngestJobConfiguration.missingModule.warning", moduleName)); //NON-NLS } - // Create ingest module templates. + /** + * Create ingest module templates. Each template encapsulates a module + * factory, the module settings for this context, and an enabled flag. + */ for (IngestModuleFactory moduleFactory : moduleFactories) { - IngestModuleTemplate moduleTemplate = new IngestModuleTemplate(moduleFactory, loadJobSettings(moduleFactory)); + IngestModuleTemplate moduleTemplate = new IngestModuleTemplate(moduleFactory, loadModuleSettings(moduleFactory)); String moduleName = moduleTemplate.getModuleName(); if (enabledModuleNames.contains(moduleName)) { moduleTemplate.setEnabled(true); @@ -221,8 +212,10 @@ public class IngestJobConfiguration { this.moduleTemplates.add(moduleTemplate); } - // Update the enabled/disabled ingest module settings to reflect any - // missing modules or newly discovered modules. + /** + * Update the enabled/disabled ingest module settings for this context + * to reflect any missing modules or newly discovered modules. + */ ModuleSettings.setConfigSetting(this.context, ENABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(enabledModuleNames)); ModuleSettings.setConfigSetting(this.context, DISABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(disabledModuleNames)); @@ -235,15 +228,13 @@ public class IngestJobConfiguration { } /** - * RJCTODO + * Gets the module names for a given key for this context. * - * @param key - * @param defaultSetting - * @return + * @param key The key string. + * @param defaultSetting The default list of module names. + * @return The list of module names associated with the key. */ private HashSet getModulesNamesFromSetting(String key, String defaultSetting) { - // Get the ingest modules setting from the user's config file. - // If there is no such setting yet, create the default setting. if (ModuleSettings.settingExists(this.context, key) == false) { ModuleSettings.setConfigSetting(this.context, key, defaultSetting); } @@ -274,12 +265,13 @@ public class IngestJobConfiguration { } /** - * RJCTODO + * Gets the saved or default ingest job settings for a given ingest module + * for this context. * - * @param factory - * @return + * @param factory The ingest module factory for the module. + * @return The ingest job settings. */ - private IngestModuleIngestJobSettings loadJobSettings(IngestModuleFactory factory) { + private IngestModuleIngestJobSettings loadModuleSettings(IngestModuleFactory factory) { IngestModuleIngestJobSettings settings = null; File settingsFile = new File(getModuleSettingsFilePath(factory)); if (settingsFile.exists()) { @@ -298,11 +290,12 @@ public class IngestJobConfiguration { /** * RJCTODO + * * @param factory - * @return + * @return */ private String getModuleSettingsFilePath(IngestModuleFactory factory) { - StringBuilder filePath = new StringBuilder(this.moduleSettingsFolderForContext); + StringBuilder filePath = new StringBuilder(this.moduleSettingsFolderPath); filePath.append(File.separator); filePath.append(factory.getClass().getCanonicalName()); filePath.append(MODULE_SETTINGS_FILE_EXT); @@ -311,14 +304,15 @@ public class IngestJobConfiguration { /** * RJCTODO - * @param messages */ - private void write(Messages messages) { - // Save the enabled/disabled ingest module settings for the current context. + private void store() { + /** + * Save the enabled/disabled ingest module settings. + */ HashSet enabledModuleNames = new HashSet<>(); HashSet disabledModuleNames = new HashSet<>(); for (IngestModuleTemplate moduleTemplate : moduleTemplates) { - saveModuleSettings(moduleTemplate.getModuleFactory(), moduleTemplate.getModuleSettings(), messages); + saveModuleSettings(moduleTemplate.getModuleFactory(), moduleTemplate.getModuleSettings()); String moduleName = moduleTemplate.getModuleName(); if (moduleTemplate.isEnabled()) { enabledModuleNames.add(moduleName); @@ -329,7 +323,9 @@ public class IngestJobConfiguration { ModuleSettings.setConfigSetting(this.context, ENABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(enabledModuleNames)); ModuleSettings.setConfigSetting(this.context, DISABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(disabledModuleNames)); - // Save the process unallocated space setting for the current context. + /** + * Save the process unallocated space setting. + */ String processUnalloc = Boolean.toString(this.processUnallocatedSpace); ModuleSettings.setConfigSetting(this.context, PARSE_UNALLOC_SPACE_KEY, processUnalloc); } @@ -339,17 +335,15 @@ public class IngestJobConfiguration { * * @param factory The ingest module factory for the ingest module. * @param settings The ingest job settings for the ingest module - * @param messages A collection of error and warning messages to receive any - * error messages generated. */ - private void saveModuleSettings(IngestModuleFactory factory, IngestModuleIngestJobSettings settings, Messages messages) { + private void saveModuleSettings(IngestModuleFactory factory, IngestModuleIngestJobSettings settings) { try { try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(getModuleSettingsFilePath(factory)))) { out.writeObject(settings); } } catch (IOException ex) { logger.log(Level.SEVERE, String.format("Error saving ingest job settings for %s ingest module for %s context", factory.getModuleDisplayName(), this.context), ex); //NON-NLS - messages.errors.add(NbBundle.getMessage(this.getClass(), "IngestJobConfiguration.saveJobSettings.errmsg", factory.getModuleDisplayName())); + this.warnings.add(NbBundle.getMessage(this.getClass(), "IngestJobConfiguration.saveJobSettings.errmsg", factory.getModuleDisplayName())); } } From 963a7fab622ecfc613e177eed1a37ddfd7b88605 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Sun, 16 Nov 2014 17:41:43 -0500 Subject: [PATCH 3/3] Complete ingest job configurator refactor --- .../AddImageWizardIngestConfigPanel.java | 38 +- .../autopsy/ingest/Bundle.properties | 21 +- .../autopsy/ingest/Bundle_ja.properties | 14 +- .../sleuthkit/autopsy/ingest/IngestJob.java | 11 +- .../autopsy/ingest/IngestJobConfigurator.java | 47 +- .../autopsy/ingest/IngestJobSettings.java | 141 +++--- ...Panel.form => IngestJobSettingsPanel.form} | 10 +- ...Panel.java => IngestJobSettingsPanel.java} | 52 ++- .../autopsy/ingest/IngestManager.java | 439 +++++++++--------- .../ingest/RunIngestModulesDialog.java | 21 +- 10 files changed, 413 insertions(+), 381 deletions(-) rename Core/src/org/sleuthkit/autopsy/ingest/{IngestJobConfigurationPanel.form => IngestJobSettingsPanel.form} (92%) rename Core/src/org/sleuthkit/autopsy/ingest/{IngestJobConfigurationPanel.java => IngestJobSettingsPanel.java} (91%) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java index c5cc14d262..9cc7f9e7cf 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java @@ -18,8 +18,6 @@ */ package org.sleuthkit.autopsy.casemodule; - -import org.sleuthkit.autopsy.ingest.IngestJobConfigurator; import org.openide.util.NbBundle; import java.awt.Color; import java.awt.Component; @@ -37,6 +35,9 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.Content; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; +import org.sleuthkit.autopsy.ingest.IngestJobSettings; +import org.sleuthkit.autopsy.ingest.IngestJobSettingsPanel; +import org.sleuthkit.autopsy.ingest.IngestManager; /** * second panel of add image wizard, allows user to configure ingest modules. * @@ -46,7 +47,8 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel { private static final Logger logger = Logger.getLogger(AddImageWizardIngestConfigPanel.class.getName()); - private IngestJobConfigurator ingestConfig; + private IngestJobSettings ingestJobSettings; + /** * The visual component that displays this panel. If you need to access the * component from this class, just use getComponent(). @@ -60,10 +62,10 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel messages = ingestConfig.getIngestJobConfigWarnings(); + this.ingestJobSettings = new IngestJobSettings(AddImageWizardIngestConfigPanel.class.getCanonicalName()); + List messages = this.ingestJobSettings.getWarnings(); if (messages.isEmpty() == false) { StringBuilder warning = new StringBuilder(); for (String message : messages) { @@ -95,7 +97,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel messages = this.ingestJobSettings.getWarnings(); + if (messages.isEmpty() == false) { + StringBuilder warning = new StringBuilder(); + for (String message : messages) { + warning.append(message).append("\n"); + } + JOptionPane.showMessageDialog(null, warning.toString()); + } + // Start ingest if it hasn't already been started readyToIngest = true; startIngest(); @@ -202,9 +212,11 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel startJob(Content dataSource, List ingestModuleTemplates, boolean processUnallocatedSpace) { + static List startJob(Content dataSource, IngestJobSettings settings) { List errors = new ArrayList<>(); if (IngestJob.jobCreationIsEnabled) { long jobId = nextJobId.incrementAndGet(); - IngestJob job = new IngestJob(jobId, dataSource, processUnallocatedSpace); + IngestJob job = new IngestJob(jobId, dataSource, settings.getProcessUnallocatedSpace()); IngestJob.jobsById.put(jobId, job); - errors = job.start(ingestModuleTemplates); + errors = job.start(settings.getEnabledIngestModuleTemplates()); if (errors.isEmpty() && job.hasIngestPipeline()) { IngestManager.getInstance().fireIngestJobStarted(jobId); IngestJob.logger.log(Level.INFO, "Ingest job {0} started", jobId); diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurator.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurator.java index 22dc882b31..ee1d65c115 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurator.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurator.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.ingest; -import java.util.ArrayList; import java.util.List; import javax.swing.JPanel; import org.sleuthkit.datamodel.Content; @@ -28,34 +27,33 @@ import org.sleuthkit.datamodel.Content; * for a particular context and for launching ingest jobs that process one or * more data sources using the ingest job configuration. * - * @deprecated Use the IngestModuleConfiguration and IngestJobConfigurationPanel - * and IngestManager.startIngestJob() or IngestManager.startIngestJobNoUI() - * instead. // RJCTODO + * @deprecated Use the IngestModuleSettings and IngestJobConfigurationPanel + * classes and IngestManager.startIngestJob() instead. */ @Deprecated public final class IngestJobConfigurator { private final IngestJobSettings settings; - private final IngestJobConfigurationPanel ingestConfigPanel; + private final IngestJobSettingsPanel settingsPanel; /** - * Constructs an ingest job launcher that creates and persists an ingest job - * configuration for a particular context and launches ingest jobs that - * process one or more data sources using the ingest job configuration. + * Constructs an ingest job launcher that creates and persists ingest job + * settings for a particular context and launches ingest jobs that + * process one or more data sources using the settings. * * @param context The context identifier. */ @Deprecated public IngestJobConfigurator(String context) { this.settings = new IngestJobSettings(context); - this.ingestConfigPanel = new IngestJobConfigurationPanel(settings); + this.settingsPanel = new IngestJobSettingsPanel(settings); } /** - * Gets any warnings generated when the persisted ingest job configuration - * for the specified context is retrieved and loaded. + * Gets any warnings generated when the persisted ingest job settings + * for the specified context are loaded or saved. * - * @return A collection of warning messages. + * @return A collection of warning messages, possibly empty. */ @Deprecated public List getIngestJobConfigWarnings() { @@ -64,18 +62,17 @@ public final class IngestJobConfigurator { /** * Gets the user interface panel the launcher uses to obtain the user's - * ingest job configuration for the specified context. + * ingest job settings for the specified context. * - * @return A JPanel with components that can be used to create an ingest job - * configuration. + * @return The panel. */ @Deprecated public JPanel getIngestJobConfigPanel() { - return ingestConfigPanel; + return settingsPanel; } /** - * Persists the ingest job configuration for the specified context. + * Persists the ingest job settings for the specified context. */ @Deprecated public void saveIngestJobConfig() { @@ -84,23 +81,15 @@ public final class IngestJobConfigurator { /** * Launches ingest jobs for one or more data sources using the ingest job - * configuration for the selected context. + * settings for the specified context. * * @param dataSources The data sources to ingest. */ @Deprecated public void startIngestJobs(List dataSources) { - // Filter out the disabled ingest module templates. - List enabledModuleTemplates = new ArrayList<>(); - List moduleTemplates = this.settings.getIngestModuleTemplates(); - for (IngestModuleTemplate moduleTemplate : moduleTemplates) { - if (moduleTemplate.isEnabled()) { - enabledModuleTemplates.add(moduleTemplate); - } - } - - if ((!enabledModuleTemplates.isEmpty()) && (dataSources != null) && (!dataSources.isEmpty())) { - IngestManager.getInstance().startIngestJobs(dataSources, enabledModuleTemplates, this.settings.getProcessUnallocatedSpace()); + IngestManager ingestManager = IngestManager.getInstance(); + for (Content dataSource : dataSources) { + ingestManager.startIngestJob(dataSource, this.settings, true); } } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java index 34486b762d..b53cc69e95 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettings.java @@ -38,17 +38,18 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.Logger; /** - * The ingest job settings for a particular context. + * Encapsulates the ingest job settings for a particular context such as the Add + * Data Source wizard or the Run Ingest Modules dialog. */ public class IngestJobSettings { - private static final String ENABLED_INGEST_MODULES_KEY = "Enabled_Ingest_Modules"; //NON-NLS - private static final String DISABLED_INGEST_MODULES_KEY = "Disabled_Ingest_Modules"; //NON-NLS + private static final String ENABLED_MODULES_KEY = "Enabled_Ingest_Modules"; //NON-NLS + private static final String DISABLED_MODULES_KEY = "Disabled_Ingest_Modules"; //NON-NLS private static final String PARSE_UNALLOC_SPACE_KEY = "Process_Unallocated_Space"; //NON-NLS + private static final String PROCESS_UNALLOC_SPACE_DEFAULT = "true"; //NON-NLS private static final String MODULE_SETTINGS_FOLDER = "IngestModuleSettings"; //NON-NLS private static final String MODULE_SETTINGS_FOLDER_PATH = Paths.get(PlatformUtil.getUserConfigDirectory(), IngestJobSettings.MODULE_SETTINGS_FOLDER).toAbsolutePath().toString(); private static final String MODULE_SETTINGS_FILE_EXT = ".settings"; //NON-NLS - private static final String PROCESS_UNALLOC_SPACE_DEFAULT = "true"; private static final Logger logger = Logger.getLogger(IngestJobSettings.class.getName()); private final String context; private String moduleSettingsFolderPath; @@ -71,17 +72,17 @@ public class IngestJobSettings { } /** - * Saves the ingest job settings for this context. + * Saves these ingest job settings. */ public void save() { this.store(); } /** - * Gets and clears any warnings associated with the ingest job settings for - * this context. + * Gets and clears any accumulated warnings associated with these ingest job + * settings. * - * @return A collection of warning messages, possibly empty. + * @return A list of warning messages, possibly empty. */ public List getWarnings() { List warningMessages = new ArrayList<>(this.warnings); @@ -90,18 +91,34 @@ public class IngestJobSettings { } /** - * Gets the ingest module templates for this context. + * Gets the ingest module templates part of these ingest job settings. * - * @return A list of the ingest module templates. + * @return The list of ingest module templates. */ List getIngestModuleTemplates() { return Collections.unmodifiableList(this.moduleTemplates); } /** - * Sets the ingest module templates for this context. + * Gets the enabled ingest module templates part of these ingest job + * settings. * - * @param moduleTemplates The list of ingest module templates. + * @return The list of enabled ingest module templates. + */ + List getEnabledIngestModuleTemplates() { + List enabledModuleTemplates = new ArrayList<>(); + for (IngestModuleTemplate moduleTemplate : this.moduleTemplates) { + if (moduleTemplate.isEnabled()) { + enabledModuleTemplates.add(moduleTemplate); + } + } + return enabledModuleTemplates; + } + + /** + * Sets the ingest module templates part of these ingest job settings. + * + * @param moduleTemplates The ingest module templates. */ void setIngestModuleTemplates(List moduleTemplates) { this.moduleTemplates.clear(); @@ -109,7 +126,8 @@ public class IngestJobSettings { } /** - * Gets the process unallocated space flag for this context. + * Gets the process unallocated space flag part of these ingest job + * settings. * * @return True or false. */ @@ -118,7 +136,7 @@ public class IngestJobSettings { } /** - * Sets the process unallocated space flag for this context. + * Sets the process unallocated space flag for these ingest job settings. * * @param processUnallocatedSpace True or false. */ @@ -127,31 +145,22 @@ public class IngestJobSettings { } /** - * Creates the folder for saving individual ingest module settings for this - * context, if it does not already exist. + * Creates the folder for saving the individual ingest module settings part + * of these ingest job settings. */ private void createSavedModuleSettingsFolder() { try { Path folder = Paths.get(IngestJobSettings.MODULE_SETTINGS_FOLDER_PATH, context); Files.createDirectories(folder); this.moduleSettingsFolderPath = folder.toAbsolutePath().toString(); - } catch (IOException ex) { - logger.log(Level.SEVERE, "Failed to create ingest module settings directory", ex); //NON-NLS - this.warnings.add(NbBundle.getMessage(IngestJobSettings.class, "IngestJobConfiguration.createModuleSettingsFolderForContext.exception.msg")); //NON-NLS - - // RJCTODO: Add this sort of code to clients, move bundle property to clients -// JOptionPane.showMessageDialog(null, -// NbBundle.getMessage(this.getClass(), -// "IngestJobConfiguration.createModuleSettingsFolderForContext.exception.msg"), -// NbBundle.getMessage(this.getClass(), -// "IngestJobConfigurator.createModuleSettingsFolderForContext.exception.title"), -// JOptionPane.ERROR_MESSAGE); + } catch (IOException | SecurityException ex) { + logger.log(Level.SEVERE, "Failed to create ingest module settings directory " + this.moduleSettingsFolderPath, ex); //NON-NLS + this.warnings.add(NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.createModuleSettingsFolder.warning")); //NON-NLS } } /** - * Loads the saved or default ingest job settings for this context into - * memory. + * Loads the saved or default ingest job settings context into memory. */ private void load() { /** @@ -168,8 +177,8 @@ public class IngestJobSettings { * Get the enabled/disabled ingest modules settings for this context. By * default, all loaded modules are enabled. */ - HashSet enabledModuleNames = getModulesNamesFromSetting(IngestJobSettings.ENABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(loadedModuleNames)); - HashSet disabledModuleNames = getModulesNamesFromSetting(IngestJobSettings.DISABLED_INGEST_MODULES_KEY, ""); //NON-NLS + HashSet enabledModuleNames = getModulesNamesFromSetting(IngestJobSettings.ENABLED_MODULES_KEY, makeCommaSeparatedValuesList(loadedModuleNames)); + HashSet disabledModuleNames = getModulesNamesFromSetting(IngestJobSettings.DISABLED_MODULES_KEY, ""); //NON-NLS /** * Check for missing modules and create warnings if any are found. @@ -188,7 +197,9 @@ public class IngestJobSettings { for (String moduleName : missingModuleNames) { enabledModuleNames.remove(moduleName); disabledModuleNames.remove(moduleName); - this.warnings.add(NbBundle.getMessage(IngestJobSettings.class, "IngestJobConfiguration.missingModule.warning", moduleName)); //NON-NLS + String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.missingModule.warning", moduleName); //NON-NLS + logger.log(Level.WARNING, warning); + this.warnings.add(warning); } /** @@ -216,19 +227,19 @@ public class IngestJobSettings { * Update the enabled/disabled ingest module settings for this context * to reflect any missing modules or newly discovered modules. */ - ModuleSettings.setConfigSetting(this.context, ENABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(enabledModuleNames)); - ModuleSettings.setConfigSetting(this.context, DISABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(disabledModuleNames)); + ModuleSettings.setConfigSetting(this.context, IngestJobSettings.ENABLED_MODULES_KEY, makeCommaSeparatedValuesList(enabledModuleNames)); + ModuleSettings.setConfigSetting(this.context, IngestJobSettings.DISABLED_MODULES_KEY, makeCommaSeparatedValuesList(disabledModuleNames)); // Get the process unallocated space flag setting. If the setting does // not exist yet, default it to true. - if (ModuleSettings.settingExists(this.context, PARSE_UNALLOC_SPACE_KEY) == false) { - ModuleSettings.setConfigSetting(this.context, PARSE_UNALLOC_SPACE_KEY, "true"); //NON-NLS + if (ModuleSettings.settingExists(this.context, IngestJobSettings.PARSE_UNALLOC_SPACE_KEY) == false) { + ModuleSettings.setConfigSetting(this.context, IngestJobSettings.PARSE_UNALLOC_SPACE_KEY, IngestJobSettings.PROCESS_UNALLOC_SPACE_DEFAULT); } - this.processUnallocatedSpace = Boolean.parseBoolean(ModuleSettings.getConfigSetting(this.context, PARSE_UNALLOC_SPACE_KEY)); + this.processUnallocatedSpace = Boolean.parseBoolean(ModuleSettings.getConfigSetting(this.context, IngestJobSettings.PARSE_UNALLOC_SPACE_KEY)); } /** - * Gets the module names for a given key for this context. + * Gets the module names for a given key within these ingest job settings. * * @param key The key string. * @param defaultSetting The default list of module names. @@ -266,10 +277,10 @@ public class IngestJobSettings { /** * Gets the saved or default ingest job settings for a given ingest module - * for this context. + * for these ingest job settings. * - * @param factory The ingest module factory for the module. - * @return The ingest job settings. + * @param factory The ingest module factory for an ingest module. + * @return The ingest module settings. */ private IngestModuleIngestJobSettings loadModuleSettings(IngestModuleFactory factory) { IngestModuleIngestJobSettings settings = null; @@ -278,8 +289,9 @@ public class IngestJobSettings { try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(settingsFile.getAbsolutePath()))) { settings = (IngestModuleIngestJobSettings) in.readObject(); } catch (IOException | ClassNotFoundException ex) { - String logMessage = String.format("Error loading ingest job settings for %s module for %s context, using defaults", factory.getModuleDisplayName(), this.context); //NON-NLS -// logger.log(Level.WARNING, logMessage, ex); RJCTODO + String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.moduleSettingsLoad.warning", factory.getModuleDisplayName(), this.context); //NON-NLS + logger.log(Level.WARNING, warning, ex); + this.warnings.add(warning); } } if (settings == null) { @@ -289,21 +301,20 @@ public class IngestJobSettings { } /** - * RJCTODO + * Returns the absolute path for the ingest job settings file for a given + * ingest module for these ingest job settings. * - * @param factory - * @return + * @param factory The ingest module factory for an ingest module. + * @return The file path. */ private String getModuleSettingsFilePath(IngestModuleFactory factory) { - StringBuilder filePath = new StringBuilder(this.moduleSettingsFolderPath); - filePath.append(File.separator); - filePath.append(factory.getClass().getCanonicalName()); - filePath.append(MODULE_SETTINGS_FILE_EXT); - return filePath.toString(); + String fileName = factory.getClass().getCanonicalName() + IngestJobSettings.MODULE_SETTINGS_FILE_EXT; + Path path = Paths.get(this.moduleSettingsFolderPath, fileName); + return path.toAbsolutePath().toString(); } /** - * RJCTODO + * Saves the ingest job settings for this context. */ private void store() { /** @@ -320,20 +331,21 @@ public class IngestJobSettings { disabledModuleNames.add(moduleName); } } - ModuleSettings.setConfigSetting(this.context, ENABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(enabledModuleNames)); - ModuleSettings.setConfigSetting(this.context, DISABLED_INGEST_MODULES_KEY, makeCommaSeparatedList(disabledModuleNames)); + ModuleSettings.setConfigSetting(this.context, ENABLED_MODULES_KEY, makeCommaSeparatedValuesList(enabledModuleNames)); + ModuleSettings.setConfigSetting(this.context, DISABLED_MODULES_KEY, makeCommaSeparatedValuesList(disabledModuleNames)); /** - * Save the process unallocated space setting. + * Save the process unallocated space setting. */ String processUnalloc = Boolean.toString(this.processUnallocatedSpace); ModuleSettings.setConfigSetting(this.context, PARSE_UNALLOC_SPACE_KEY, processUnalloc); } /** - * Serializes the ingest job settings for an ingest module for this context. + * Serializes the ingest job settings for this context for a given ingest + * module. * - * @param factory The ingest module factory for the ingest module. + * @param factory The ingest module factory for the module. * @param settings The ingest job settings for the ingest module */ private void saveModuleSettings(IngestModuleFactory factory, IngestModuleIngestJobSettings settings) { @@ -342,19 +354,20 @@ public class IngestJobSettings { out.writeObject(settings); } } catch (IOException ex) { - logger.log(Level.SEVERE, String.format("Error saving ingest job settings for %s ingest module for %s context", factory.getModuleDisplayName(), this.context), ex); //NON-NLS - this.warnings.add(NbBundle.getMessage(this.getClass(), "IngestJobConfiguration.saveJobSettings.errmsg", factory.getModuleDisplayName())); + String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.moduleSettingsSave.warning", factory.getModuleDisplayName(), this.context); //NON-NLS + logger.log(Level.SEVERE, warning, ex); + this.warnings.add(warning); } } /** - * RJCTODO: Consider making this a generally available utility; there might - * be a cleaner impl in Core Java 2 + * Makes a comma-separated values list from a hash set of strings. * - * @param input - * @return + * @param input A hash set of strings. + * @return The contents of the hash set as a single string of + * comma-separated values. */ - private static String makeCommaSeparatedList(HashSet input) { + private static String makeCommaSeparatedValuesList(HashSet input) { if (input == null || input.isEmpty()) { return ""; } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurationPanel.form b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.form similarity index 92% rename from Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurationPanel.form rename to Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.form index 4119772238..08b078aba9 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurationPanel.form +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.form @@ -144,10 +144,10 @@ - + - + @@ -160,7 +160,7 @@ - + @@ -221,10 +221,10 @@ - + - + diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurationPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.java similarity index 91% rename from Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurationPanel.java rename to Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.java index 06756f972b..738313cf31 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobConfigurationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.java @@ -35,41 +35,47 @@ import javax.swing.table.TableColumn; import org.sleuthkit.autopsy.corecomponents.AdvancedConfigurationDialog; /** - * User interface component to allow a user to set ingest module options and - * enable/disable the modules. + * User interface component to allow a user to make ingest job settings. */ -class IngestJobConfigurationPanel extends javax.swing.JPanel { +public final class IngestJobSettingsPanel extends javax.swing.JPanel { - private final IngestJobSettings config; + private final IngestJobSettings settings; private final List modules; private IngestModuleModel selectedModule; - IngestJobConfigurationPanel(IngestJobSettings config) { - this.config = config; + /** + * Construct a user interface component to allow a user to make ingest job + * settings. + * + * @param settings The initial settings for the ingest job. + */ + public IngestJobSettingsPanel(IngestJobSettings settings) { + this.settings = settings; this.modules = new ArrayList<>(); - for (IngestModuleTemplate moduleTemplate : config.getIngestModuleTemplates()) { + for (IngestModuleTemplate moduleTemplate : settings.getIngestModuleTemplates()) { this.modules.add(new IngestModuleModel(moduleTemplate)); - } + } initComponents(); customizeComponents(); } - + /** - * RJCTODO - * @return + * Gets the ingest settings made using this panel. + * + * @return The settings. */ - IngestJobSettings getConfig() { + IngestJobSettings getSettings() { List moduleTemplates = new ArrayList<>(); for (IngestModuleModel module : modules) { IngestModuleTemplate moduleTemplate = module.getIngestModuleTemplate(); if (module.hasModuleSettingsPanel()) { - IngestModuleIngestJobSettings settings = module.getModuleSettingsPanel().getSettings(); - moduleTemplate.setModuleSettings(settings); + IngestModuleIngestJobSettings moduleSettings = module.getModuleSettingsPanel().getSettings(); + moduleTemplate.setModuleSettings(moduleSettings); } moduleTemplates.add(moduleTemplate); } - this.config.setIngestModuleTemplates(moduleTemplates); - return this.config; + this.settings.setIngestModuleTemplates(moduleTemplates); + return this.settings; } private void customizeComponents() { @@ -115,7 +121,7 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel { } }); - processUnallocCheckbox.setSelected(this.config.getProcessUnallocatedSpace()); + processUnallocCheckbox.setSelected(this.settings.getProcessUnallocatedSpace()); } /** @@ -162,8 +168,8 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel { jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(160, 160, 160))); jPanel1.setPreferredSize(new java.awt.Dimension(338, 257)); - advancedButton.setText(org.openide.util.NbBundle.getMessage(IngestJobConfigurationPanel.class, "IngestJobConfigurationPanel.advancedButton.text")); // NOI18N - advancedButton.setActionCommand(org.openide.util.NbBundle.getMessage(IngestJobConfigurationPanel.class, "IngestJobConfigurationPanel.advancedButton.actionCommand")); // NOI18N + advancedButton.setText(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.advancedButton.text")); // NOI18N + advancedButton.setActionCommand(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.advancedButton.actionCommand")); // NOI18N advancedButton.setEnabled(false); advancedButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -171,7 +177,7 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel { } }); - descriptionLabel.setText(org.openide.util.NbBundle.getMessage(IngestJobConfigurationPanel.class, "IngestJobConfigurationPanel.descriptionLabel.text")); // NOI18N + descriptionLabel.setText(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.descriptionLabel.text")); // NOI18N jScrollPane1.setBorder(null); jScrollPane1.setPreferredSize(new java.awt.Dimension(250, 180)); @@ -210,8 +216,8 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel { processUnallocPanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(160, 160, 160))); - processUnallocCheckbox.setText(org.openide.util.NbBundle.getMessage(IngestJobConfigurationPanel.class, "IngestJobConfigurationPanel.processUnallocCheckbox.text")); // NOI18N - processUnallocCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(IngestJobConfigurationPanel.class, "IngestJobConfigurationPanel.processUnallocCheckbox.toolTipText")); // NOI18N + processUnallocCheckbox.setText(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.processUnallocCheckbox.text")); // NOI18N + processUnallocCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(IngestJobSettingsPanel.class, "IngestJobSettingsPanel.processUnallocCheckbox.toolTipText")); // NOI18N processUnallocCheckbox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { processUnallocCheckboxActionPerformed(evt); @@ -263,7 +269,7 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel { }// //GEN-END:initComponents private void processUnallocCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_processUnallocCheckboxActionPerformed - this.config.setProcessUnallocatedSpace(processUnallocCheckbox.isSelected()); + this.settings.setProcessUnallocatedSpace(processUnallocCheckbox.isSelected()); }//GEN-LAST:event_processUnallocCheckboxActionPerformed private void advancedButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_advancedButtonActionPerformed diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index ccee8b482e..3a9a58a959 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -46,7 +46,8 @@ import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; /** - * Manages the execution of ingest jobs. + * Manages the creation and execution of ingest jobs, i.e., processing of data + * sources by ingest modules. */ public class IngestManager { @@ -64,7 +65,7 @@ public class IngestManager { private final ExecutorService fileIngestThreadPool; private final ExecutorService fireIngestEventsThreadPool = Executors.newSingleThreadExecutor(); private final AtomicLong nextThreadId = new AtomicLong(0L); - private final ConcurrentHashMap> startIngestJobsTasks = new ConcurrentHashMap<>(); // Maps thread ids to cancellation handles. + private final ConcurrentHashMap> startIngestJobsCallables = new ConcurrentHashMap<>(); // Maps thread ids to cancellation handles. private final AtomicLong ingestErrorMessagePosts = new AtomicLong(0L); private final ConcurrentHashMap ingestThreadActivitySnapshots = new ConcurrentHashMap<>(); // Maps ingest thread ids to progress ingestThreadActivitySnapshots. private final ConcurrentHashMap ingestModuleRunTimes = new ConcurrentHashMap<>(); @@ -73,6 +74,60 @@ public class IngestManager { private volatile IngestMessageTopComponent ingestMessageBox; private int numberOfFileIngestThreads = DEFAULT_NUMBER_OF_FILE_INGEST_THREADS; + /** + * Ingest job events. + */ + public enum IngestJobEvent { + + /** + * Property change event fired when an ingest job is started. The old + * value of the PropertyChangeEvent object is set to the ingest job id, + * and the new value is set to null. + */ + STARTED, + /** + * Property change event fired when an ingest job is completed. The old + * value of the PropertyChangeEvent object is set to the ingest job id, + * and the new value is set to null. + */ + COMPLETED, + /** + * Property change event fired when an ingest job is canceled. The old + * value of the PropertyChangeEvent object is set to the ingest job id, + * and the new value is set to null. + */ + CANCELLED, + }; + + /** + * Ingest module events. + */ + public enum IngestModuleEvent { + + /** + * Property change event fired when an ingest module adds new data to a + * case, usually by posting to the blackboard. The old value of the + * PropertyChangeEvent is a ModuleDataEvent object, and the new value is + * set to null. + */ + DATA_ADDED, + /** + * Property change event fired when an ingest module adds new content to + * a case or changes a recorded attribute of existing content. For + * example, if a module adds an extracted or carved file to a case, the + * module should fire this event. The old value of the + * PropertyChangeEvent is a ModuleContentEvent object, and the new value + * is set to null. + */ + CONTENT_CHANGED, + /** + * Property change event fired when the ingest of a file is completed. + * The old value of the PropertyChangeEvent is the Autopsy object ID of + * the file. The new value is the AbstractFile for that ID. + */ + FILE_DONE, + }; + /** * Gets the ingest manager. * @@ -90,6 +145,123 @@ public class IngestManager { return instance; } + /** + * Gets the number of file ingest threads the ingest manager will use to do + * ingest jobs. + * + * @return The number of file ingest threads. + */ + public int getNumberOfFileIngestThreads() { + return numberOfFileIngestThreads; + } + + /** + * Starts an ingest job, i.e., processing by ingest modules, for a data + * source. + * + * @param dataSource The data source to be processed. + * @param settings The ingest job settings. + * @param doStartupErrorsMsgBox Whether or not to display ingest module + * startup errors in a message box. + */ + public synchronized void startIngestJob(Content dataSource, IngestJobSettings settings, boolean doStartupErrorsMsgBox) { + if (!isIngestRunning()) { + clearIngestMessageBox(); + } + + if (!ingestMonitor.isRunning()) { + ingestMonitor.start(); + } + + long taskId = nextThreadId.incrementAndGet(); + Future task = startIngestJobsThreadPool.submit(new StartIngestJobsCallable(taskId, dataSource, settings, doStartupErrorsMsgBox)); + startIngestJobsCallables.put(taskId, task); + } + + /** + * Queries whether any ingest jobs are in progress. + * + * @return True or false. + */ + public boolean isIngestRunning() { + return IngestJob.ingestJobsAreRunning(); + } + + /** + * Cancels all ingest jobs in progress. + */ + public void cancelAllIngestJobs() { + // Stop creating new ingest jobs. + for (Future handle : startIngestJobsCallables.values()) { + handle.cancel(true); + } + + // Cancel all the jobs already created. + IngestJob.cancelAllJobs(); + } + + /** + * Adds an ingest job event property change listener. + * + * @param listener The PropertyChangeListener to register. + */ + public void addIngestJobEventListener(final PropertyChangeListener listener) { + ingestJobEventPublisher.addPropertyChangeListener(listener); + } + + /** + * Removes an ingest job event property change listener. + * + * @param listener The PropertyChangeListener to unregister. + */ + public void removeIngestJobEventListener(final PropertyChangeListener listener) { + ingestJobEventPublisher.removePropertyChangeListener(listener); + } + + /** + * Adds an ingest module event property change listener. + * + * @param listener The PropertyChangeListener to register. + */ + public void addIngestModuleEventListener(final PropertyChangeListener listener) { + ingestModuleEventPublisher.addPropertyChangeListener(listener); + } + + /** + * Removes an ingest module event property change listener. + * + * @param listener The PropertyChangeListener to unregister. + */ + public void removeIngestModuleEventListener(final PropertyChangeListener listener) { + ingestModuleEventPublisher.removePropertyChangeListener(listener); + } + + /** + * Adds an ingest job and ingest module event property change listener. + * + * @param listener The PropertyChangeListener to register. + * @deprecated Use addIngestJobEventListener() and/or + * addIngestModuleEventListener(). + */ + @Deprecated + public static void addPropertyChangeListener(final PropertyChangeListener listener) { + instance.ingestJobEventPublisher.addPropertyChangeListener(listener); + instance.ingestModuleEventPublisher.addPropertyChangeListener(listener); + } + + /** + * Remove an ingest job and ingest module event property change listener. + * + * @param listener The PropertyChangeListener to unregister. + * @deprecated Use removeIngestJobEventListener() and/or + * removeIngestModuleEventListener(). + */ + @Deprecated + public static void removePropertyChangeListener(final PropertyChangeListener listener) { + instance.ingestJobEventPublisher.removePropertyChangeListener(listener); + instance.ingestModuleEventPublisher.removePropertyChangeListener(listener); + } + /** * Starts the ingest monitor and submits task execution tasks (Callable * objects) to the data source ingest and file ingest thread pools. The task @@ -97,7 +269,7 @@ public class IngestManager { * the application runs */ private IngestManager() { - startDataSourceIngestTask(); + startDataSourceIngestThread(); numberOfFileIngestThreads = UserPreferences.numberOfFileIngestThreads(); if ((numberOfFileIngestThreads < MIN_NUMBER_OF_FILE_INGEST_THREADS) || (numberOfFileIngestThreads > MAX_NUMBER_OF_FILE_INGEST_THREADS)) { @@ -106,7 +278,7 @@ public class IngestManager { } fileIngestThreadPool = Executors.newFixedThreadPool(numberOfFileIngestThreads); for (int i = 0; i < numberOfFileIngestThreads; ++i) { - startFileIngestTask(); + startFileIngestThread(); } } @@ -119,20 +291,11 @@ public class IngestManager { ingestMessageBox = IngestMessageTopComponent.findInstance(); } - /** - * Gets the number of file ingest threads the ingest manager will use. - * - * @return The number of file ingest threads. - */ - public int getNumberOfFileIngestThreads() { - return numberOfFileIngestThreads; - } - /** * Submits a ExecuteIngestTasksTask Callable to the data source ingest task * thread pool. */ - private void startDataSourceIngestTask() { + private void startDataSourceIngestThread() { long threadId = nextThreadId.incrementAndGet(); dataSourceIngestThreadPool.submit(new ExecuteIngestTasksRunnable(threadId, IngestTasksScheduler.getInstance().getDataSourceIngestTaskQueue())); ingestThreadActivitySnapshots.put(threadId, new IngestThreadActivitySnapshot(threadId)); @@ -142,22 +305,12 @@ public class IngestManager { * Submits a ExecuteIngestTasksTask Callable to the data source ingest * thread pool. */ - private void startFileIngestTask() { + private void startFileIngestThread() { long threadId = nextThreadId.incrementAndGet(); fileIngestThreadPool.submit(new ExecuteIngestTasksRunnable(threadId, IngestTasksScheduler.getInstance().getFileIngestTaskQueue())); ingestThreadActivitySnapshots.put(threadId, new IngestThreadActivitySnapshot(threadId)); } - synchronized void startIngestJobs(final List dataSources, final List moduleTemplates, boolean processUnallocatedSpace) { - if (!isIngestRunning()) { - clearIngestMessageBox(); - } - - long taskId = nextThreadId.incrementAndGet(); - Future task = startIngestJobsThreadPool.submit(new StartIngestJobsCallable(taskId, dataSources, moduleTemplates, processUnallocatedSpace)); - startIngestJobsTasks.put(taskId, task); - } - private void subscribeToCaseEvents() { Case.addPropertyChangeListener(new PropertyChangeListener() { @Override @@ -191,15 +344,6 @@ public class IngestManager { ingestErrorMessagePosts.set(0); } - /** - * Test if any ingest jobs are in progress. - * - * @return True if any ingest jobs are in progress, false otherwise. - */ - public boolean isIngestRunning() { - return IngestJob.ingestJobsAreRunning(); - } - /** * Called each time a module in a data source pipeline starts * @@ -292,132 +436,6 @@ public class IngestManager { return new ArrayList<>(ingestThreadActivitySnapshots.values()); } - public void cancelAllIngestJobs() { - // Stop creating new ingest jobs. - for (Future handle : startIngestJobsTasks.values()) { - handle.cancel(true); - } - - // Cancel all the jobs already created. - IngestJob.cancelAllJobs(); - } - - /** - * Ingest job events. - */ - public enum IngestJobEvent { - - /** - * Property change event fired when an ingest job is started. The old - * value of the PropertyChangeEvent object is set to the ingest job id, - * and the new value is set to null. - */ - STARTED, - /** - * Property change event fired when an ingest job is completed. The old - * value of the PropertyChangeEvent object is set to the ingest job id, - * and the new value is set to null. - */ - COMPLETED, - /** - * Property change event fired when an ingest job is canceled. The old - * value of the PropertyChangeEvent object is set to the ingest job id, - * and the new value is set to null. - */ - CANCELLED, - }; - - /** - * Ingest module events. - */ - public enum IngestModuleEvent { - - /** - * Property change event fired when an ingest module adds new data to a - * case, usually by posting to the blackboard. The old value of the - * PropertyChangeEvent is a ModuleDataEvent object, and the new value is - * set to null. - */ - DATA_ADDED, - /** - * Property change event fired when an ingest module adds new content to - * a case or changes a recorded attribute of existing content. For - * example, if a module adds an extracted or carved file to a case, the - * module should fire this event. The old value of the - * PropertyChangeEvent is a ModuleContentEvent object, and the new value - * is set to null. - */ - CONTENT_CHANGED, - /** - * Property change event fired when the ingest of a file is completed. - * The old value of the PropertyChangeEvent is the Autopsy object ID of - * the file. The new value is the AbstractFile for that ID. - */ - FILE_DONE, - }; - - /** - * Add an ingest job event property change listener. - * - * @param listener The PropertyChangeListener to register. - */ - public void addIngestJobEventListener(final PropertyChangeListener listener) { - ingestJobEventPublisher.addPropertyChangeListener(listener); - } - - /** - * Remove an ingest job event property change listener. - * - * @param listener The PropertyChangeListener to unregister. - */ - public void removeIngestJobEventListener(final PropertyChangeListener listener) { - ingestJobEventPublisher.removePropertyChangeListener(listener); - } - - /** - * Add an ingest module event property change listener. - * - * @param listener The PropertyChangeListener to register. - */ - public void addIngestModuleEventListener(final PropertyChangeListener listener) { - ingestModuleEventPublisher.addPropertyChangeListener(listener); - } - - /** - * Remove an ingest module event property change listener. - * - * @param listener The PropertyChangeListener to unregister. - */ - public void removeIngestModuleEventListener(final PropertyChangeListener listener) { - ingestModuleEventPublisher.removePropertyChangeListener(listener); - } - - /** - * Add an ingest job and ingest module event property change listener. - * - * @deprecated Use addIngestJobEventListener() and/or - * addIngestModuleEventListener(). - * @param listener The PropertyChangeListener to register. - */ - @Deprecated - public static void addPropertyChangeListener(final PropertyChangeListener listener) { - instance.ingestJobEventPublisher.addPropertyChangeListener(listener); - instance.ingestModuleEventPublisher.addPropertyChangeListener(listener); - } - - /** - * Remove an ingest job and ingest module event property change listener. - * - * @deprecated Use removeIngestJobEventListener() and/or - * removeIngestModuleEventListener(). - * @param listener The PropertyChangeListener to unregister. - */ - @Deprecated - public static void removePropertyChangeListener(final PropertyChangeListener listener) { - instance.ingestJobEventPublisher.removePropertyChangeListener(listener); - instance.ingestModuleEventPublisher.removePropertyChangeListener(listener); - } - /** * Fire an ingest event signifying an ingest job started. * @@ -513,26 +531,34 @@ public class IngestManager { } /** - * Creates ingest jobs. + * Creates and starts an ingest job, i.e., processing by ingest modules, for + * a data source. */ private final class StartIngestJobsCallable implements Callable { private final long threadId; - private final List dataSources; - private final List moduleTemplates; - private final boolean processUnallocatedSpace; + private final Content dataSource; + private final IngestJobSettings settings; + private final boolean doStartupErrorsMsgBox; private ProgressHandle progress; - StartIngestJobsCallable(long threadId, List dataSources, List moduleTemplates, boolean processUnallocatedSpace) { + StartIngestJobsCallable(long threadId, Content dataSource, IngestJobSettings settings, boolean doStartupErrorsMsgBox) { this.threadId = threadId; - this.dataSources = dataSources; - this.moduleTemplates = moduleTemplates; - this.processUnallocatedSpace = processUnallocatedSpace; + this.dataSource = dataSource; + this.settings = settings; + this.doStartupErrorsMsgBox = doStartupErrorsMsgBox; } @Override public Void call() { try { + if (Thread.currentThread().isInterrupted()) { + return null; + } + + /** + * Set up a progress bar. + */ final String displayName = NbBundle.getMessage(this.getClass(), "IngestManager.StartIngestJobsTask.run.displayName"); progress = ProgressHandleFactory.createHandle(displayName, new Cancellable() { @@ -543,62 +569,50 @@ public class IngestManager { "IngestManager.StartIngestJobsTask.run.cancelling", displayName)); } - Future handle = startIngestJobsTasks.remove(threadId); + Future handle = startIngestJobsCallables.remove(threadId); handle.cancel(true); return true; } }); - progress.start(dataSources.size()); + progress.switchToIndeterminate(); + progress.start(); - if (!ingestMonitor.isRunning()) { - ingestMonitor.start(); - } - - int dataSourceProcessed = 0; - for (Content dataSource : dataSources) { - if (Thread.currentThread().isInterrupted()) { - break; - } - - // Start an ingest job for the data source. - List errors = IngestJob.startJob(dataSource, moduleTemplates, processUnallocatedSpace); - if (!errors.isEmpty()) { - // Report the errors to the user. They have already been logged. - StringBuilder moduleStartUpErrors = new StringBuilder(); - for (IngestModuleError error : errors) { - String moduleName = error.getModuleDisplayName(); - moduleStartUpErrors.append(moduleName); - moduleStartUpErrors.append(": "); - moduleStartUpErrors.append(error.getModuleError().getLocalizedMessage()); - moduleStartUpErrors.append("\n"); - } - StringBuilder notifyMessage = new StringBuilder(); - notifyMessage.append(NbBundle.getMessage(this.getClass(), - "IngestManager.StartIngestJobsTask.run.startupErr.dlgMsg")); - notifyMessage.append("\n"); - notifyMessage.append(NbBundle.getMessage(this.getClass(), - "IngestManager.StartIngestJobsTask.run.startupErr.dlgSolution")); - notifyMessage.append("\n"); - notifyMessage.append(NbBundle.getMessage(this.getClass(), - "IngestManager.StartIngestJobsTask.run.startupErr.dlgErrorList", - moduleStartUpErrors.toString())); - notifyMessage.append("\n\n"); - JOptionPane.showMessageDialog(null, notifyMessage.toString(), - NbBundle.getMessage(this.getClass(), - "IngestManager.StartIngestJobsTask.run.startupErr.dlgTitle"), JOptionPane.ERROR_MESSAGE); - } - progress.progress(++dataSourceProcessed); - - if (!Thread.currentThread().isInterrupted()) { - break; + /** + * Create and start an ingest job for the data source. + */ + List errors = IngestJob.startJob(dataSource, this.settings); + if (!errors.isEmpty() && this.doStartupErrorsMsgBox) { + // Report the errors to the user. They have already been logged. + StringBuilder moduleStartUpErrors = new StringBuilder(); + for (IngestModuleError error : errors) { + String moduleName = error.getModuleDisplayName(); + moduleStartUpErrors.append(moduleName); + moduleStartUpErrors.append(": "); + moduleStartUpErrors.append(error.getModuleError().getLocalizedMessage()); + moduleStartUpErrors.append("\n"); } + StringBuilder notifyMessage = new StringBuilder(); + notifyMessage.append(NbBundle.getMessage(this.getClass(), + "IngestManager.StartIngestJobsTask.run.startupErr.dlgMsg")); + notifyMessage.append("\n"); + notifyMessage.append(NbBundle.getMessage(this.getClass(), + "IngestManager.StartIngestJobsTask.run.startupErr.dlgSolution")); + notifyMessage.append("\n"); + notifyMessage.append(NbBundle.getMessage(this.getClass(), + "IngestManager.StartIngestJobsTask.run.startupErr.dlgErrorList", + moduleStartUpErrors.toString())); + notifyMessage.append("\n\n"); + JOptionPane.showMessageDialog(null, notifyMessage.toString(), + NbBundle.getMessage(this.getClass(), + "IngestManager.StartIngestJobsTask.run.startupErr.dlgTitle"), JOptionPane.ERROR_MESSAGE); } } catch (Exception ex) { logger.log(Level.SEVERE, "Failed to create ingest job", ex); //NON-NLS } finally { progress.finish(); - startIngestJobsTasks.remove(threadId); + startIngestJobsCallables.remove(threadId); } + return null; } } @@ -758,4 +772,5 @@ public class IngestManager { return processedFilesCount; } } + } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java b/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java index 9f722789d2..99fe0438ea 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java @@ -44,13 +44,13 @@ public final class RunIngestModulesDialog extends JDialog { private static final String TITLE = NbBundle.getMessage(RunIngestModulesDialog.class, "IngestDialog.title.text"); private static Dimension DIMENSIONS = new Dimension(500, 300); - private List dataSources = new ArrayList<>(); - private IngestJobConfigurator ingestJobLauncher; + private final List dataSources = new ArrayList<>(); + private IngestJobSettings ingestJobSettings; public RunIngestModulesDialog(JFrame frame, String title, boolean modal) { super(frame, title, modal); - ingestJobLauncher = new IngestJobConfigurator(RunIngestModulesDialog.class.getCanonicalName()); - List messages = ingestJobLauncher.getIngestJobConfigWarnings(); + ingestJobSettings = new IngestJobSettings(RunIngestModulesDialog.class.getCanonicalName()); + List messages = ingestJobSettings.getWarnings(); if (messages.isEmpty() == false) { StringBuilder warning = new StringBuilder(); for (String message : messages) { @@ -79,28 +79,31 @@ public final class RunIngestModulesDialog extends JDialog { // set the location of the popUp Window on the center of the screen setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2); - add(ingestJobLauncher.getIngestJobConfigPanel(), BorderLayout.PAGE_START); + add(new IngestJobSettingsPanel(ingestJobSettings), BorderLayout.PAGE_START); JButton startButton = new JButton(NbBundle.getMessage(this.getClass(), "IngestDialog.startButton.title")); JButton closeButton = new JButton(NbBundle.getMessage(this.getClass(), "IngestDialog.closeButton.title")); startButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - ingestJobLauncher.saveIngestJobConfig(); - ingestJobLauncher.startIngestJobs(dataSources); + ingestJobSettings.save(); + IngestManager ingestManager = IngestManager.getInstance(); + for (Content dataSource : dataSources) { + ingestManager.startIngestJob(dataSource, ingestJobSettings, true); + } close(); } }); closeButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - ingestJobLauncher.saveIngestJobConfig(); + ingestJobSettings.save(); close(); } }); this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { - ingestJobLauncher.saveIngestJobConfig(); + ingestJobSettings.save(); close(); } });