/*
* Autopsy Forensic Browser
*
* Copyright 2012-2014 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.ingest;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* Provides data source and file ingest pipeline configurations as ordered lists
* of ingest module factory class names.
*/
final class IngestPipelinesConfiguration {
private static final Logger logger = Logger.getLogger(IngestPipelinesConfiguration.class.getName());
private static final String PIPELINES_CONFIG_FILE = "PipelineConfig.xml"; //NON-NLS
private static final String PIPELINE_ELEM = "PIPELINE"; //NON-NLS
private static final int NUMBER_OF_PIPELINE_DEFINITIONS = 3;
private static final String PIPELINE_TYPE_ATTR = "type"; //NON-NLS
private static final String STAGE_ONE_DATA_SOURCE_INGEST_PIPELINE_ELEM = "ImageAnalysisStageOne"; //NON-NLS
private static final String STAGE_TWO_DATA_SOURCE_INGEST_PIPELINE_ELEM = "ImageAnalysisStageTwo"; //NON-NLS
private static final String FILE_INGEST_PIPELINE_ELEM = "FileAnalysis"; //NON-NLS
private static final String INGEST_MODULE_ELEM = "MODULE"; //NON-NLS
private static IngestPipelinesConfiguration instance;
private final List<String> stageOneDataSourceIngestPipelineConfig = new ArrayList<>();
private final List<String> fileIngestPipelineConfig = new ArrayList<>();
private final List<String> stageTwoDataSourceIngestPipelineConfig = new ArrayList<>();
/**
* Gets the ingest pipelines configuration singleton.
*
* @return The singleton.
*/
synchronized static IngestPipelinesConfiguration getInstance() {
if (instance == null) {
Logger.getLogger(IngestPipelinesConfiguration.class.getName()).log(Level.INFO, "Creating ingest module loader instance"); //NON-NLS
instance = new IngestPipelinesConfiguration();
}
return instance;
}
/**
* Constructs an object that provides data source and file ingest pipeline
* configurations as ordered lists of ingest module factory class names.
*/
private IngestPipelinesConfiguration() {
this.readPipelinesConfigurationFile();
}
/**
* Gets the ordered list of ingest module factory class names for the file
* ingest pipeline.
*
* @return An ordered list of ingest module factory class names.
*/
List<String> getStageOneDataSourceIngestPipelineConfig() {
return new ArrayList<>(stageOneDataSourceIngestPipelineConfig);
}
/**
* Gets the ordered list of ingest module factory class names for the first
* stage data source ingest pipeline.
*
* @return An ordered list of ingest module factory class names.
*/
List<String> getFileIngestPipelineConfig() {
return new ArrayList<>(fileIngestPipelineConfig);
}
/**
* Gets the ordered list of ingest module factory class names for the second
* stage data source ingest pipeline.
*
* @return An ordered list of ingest module factory class names.
*/
List<String> getStageTwoDataSourceIngestPipelineConfig() {
return new ArrayList<>(stageTwoDataSourceIngestPipelineConfig);
}
/**
* Attempts to read the ingest pipeline configuration data from an XML file.
*/
private void readPipelinesConfigurationFile() {
try {
PlatformUtil.extractResourceToUserConfigDir(IngestPipelinesConfiguration.class, PIPELINES_CONFIG_FILE, false);
Path configFilePath = Paths.get(PlatformUtil.getUserConfigDirectory(), PIPELINES_CONFIG_FILE);
Document doc = XMLUtil.loadDoc(IngestPipelinesConfiguration.class, configFilePath.toAbsolutePath().toString());
if (doc == null) {
return;
}
// Get the document root element.
Element rootElement = doc.getDocumentElement();
if (null == rootElement) {
logger.log(Level.SEVERE, "Invalid pipelines config file"); //NON-NLS
return;
}
// Get the pipeline elements and confirm that the correct number is
// present.
NodeList pipelineElements = rootElement.getElementsByTagName(IngestPipelinesConfiguration.PIPELINE_ELEM);
int numPipelines = pipelineElements.getLength();
if (numPipelines != IngestPipelinesConfiguration.NUMBER_OF_PIPELINE_DEFINITIONS) {
logger.log(Level.SEVERE, "Invalid pipelines config file"); //NON-NLS
return;
}
// Parse the pipeline elements to populate the pipeline
// configuration lists.
List<String> pipelineConfig = null;
for (int pipelineNum = 0; pipelineNum < numPipelines; ++pipelineNum) {
Element pipelineElement = (Element) pipelineElements.item(pipelineNum);
String pipelineTypeAttr = pipelineElement.getAttribute(PIPELINE_TYPE_ATTR);
if (null != pipelineTypeAttr) {
switch (pipelineTypeAttr) {
case STAGE_ONE_DATA_SOURCE_INGEST_PIPELINE_ELEM:
pipelineConfig = this.stageOneDataSourceIngestPipelineConfig;
break;
case FILE_INGEST_PIPELINE_ELEM:
pipelineConfig = this.fileIngestPipelineConfig;
break;
case STAGE_TWO_DATA_SOURCE_INGEST_PIPELINE_ELEM:
pipelineConfig = this.stageTwoDataSourceIngestPipelineConfig;
break;
default:
logger.log(Level.SEVERE, "Invalid pipelines config file"); //NON-NLS
return;
}
}
// Create an ordered list of class names. The sequence of class
// names defines the sequence of modules in the pipeline.
if (pipelineConfig != null) {
NodeList modulesElems = pipelineElement.getElementsByTagName(INGEST_MODULE_ELEM);
int numModules = modulesElems.getLength();
for (int moduleNum = 0; moduleNum < numModules; ++moduleNum) {
Element moduleElement = (Element) modulesElems.item(moduleNum);
String className = moduleElement.getTextContent();
if (null != className && !className.isEmpty()) {
pipelineConfig.add(className);
}
}
}
}
} catch (IOException ex) {
logger.log(Level.SEVERE, "Error copying default pipeline configuration to user dir", ex); //NON-NLS
}
}
}