mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 09:17:42 +00:00
Update external results import code
This commit is contained in:
parent
2c39db9591
commit
388dc636af
56
Core/src/org/sleuthkit/autopsy/coreutils/ErrorInfo.java
Executable file
56
Core/src/org/sleuthkit/autopsy/coreutils/ErrorInfo.java
Executable file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 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.coreutils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates an error message and an associated exception, if any.
|
||||||
|
*/
|
||||||
|
final public class ErrorInfo {
|
||||||
|
private final String errorSource;
|
||||||
|
private final String message;
|
||||||
|
private final Exception exception;
|
||||||
|
|
||||||
|
public ErrorInfo(String errorSource, String message) {
|
||||||
|
this.errorSource = errorSource;
|
||||||
|
this.message = message;
|
||||||
|
this.exception = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ErrorInfo(String errorSource, String message, Exception exception) {
|
||||||
|
this.errorSource = errorSource;
|
||||||
|
this.message = message;
|
||||||
|
this.exception = exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrroSource() {
|
||||||
|
return this.errorSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return this.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasException() {
|
||||||
|
return exception != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Exception getException() {
|
||||||
|
return this.exception;
|
||||||
|
}
|
||||||
|
}
|
@ -44,11 +44,11 @@ import javax.xml.transform.TransformerException;
|
|||||||
import javax.xml.transform.TransformerFactory;
|
import javax.xml.transform.TransformerFactory;
|
||||||
import javax.xml.transform.dom.DOMSource;
|
import javax.xml.transform.dom.DOMSource;
|
||||||
import javax.xml.transform.stream.StreamResult;
|
import javax.xml.transform.stream.StreamResult;
|
||||||
import org.openide.util.Exceptions;
|
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.externalresults.ExternalResults;
|
||||||
import org.sleuthkit.autopsy.externalresults.ExternalResultsImporter;
|
import org.sleuthkit.autopsy.externalresults.ExternalResultsImporter;
|
||||||
import org.sleuthkit.autopsy.externalresults.ExternalResultsXML;
|
import org.sleuthkit.autopsy.externalresults.ExternalResultsXMLParser;
|
||||||
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
|
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
|
||||||
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
|
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||||
@ -111,7 +111,12 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM
|
|||||||
progressBar.progress(1);
|
progressBar.progress(1);
|
||||||
|
|
||||||
// Import the results of the analysis.
|
// Import the results of the analysis.
|
||||||
ExternalResultsImporter.importResultsFromXML(dataSource, resultsFilePath);
|
ExternalResults results = new ExternalResultsXMLParser(dataSource, resultsFilePath).parse();
|
||||||
|
// RJCTODO: Get error messages
|
||||||
|
ExternalResultsImporter importer = new ExternalResultsImporter();
|
||||||
|
importer.importResults(results);
|
||||||
|
// RJCTODO: Get error messages
|
||||||
|
|
||||||
progressBar.progress(2);
|
progressBar.progress(2);
|
||||||
} catch (TskCoreException | ParserConfigurationException | TransformerException | IOException ex) {
|
} catch (TskCoreException | ParserConfigurationException | TransformerException | IOException ex) {
|
||||||
Logger logger = IngestServices.getInstance().getLogger(moduleName);
|
Logger logger = IngestServices.getInstance().getLogger(moduleName);
|
||||||
@ -164,18 +169,18 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM
|
|||||||
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
|
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||||
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
|
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
|
||||||
Document doc = docBuilder.newDocument();
|
Document doc = docBuilder.newDocument();
|
||||||
Element rootElement = doc.createElement(ExternalResultsXML.ROOT_ELEM.toString());
|
Element rootElement = doc.createElement(ExternalResultsXMLParser.TagNames.ROOT_ELEM.toString());
|
||||||
doc.appendChild(rootElement);
|
doc.appendChild(rootElement);
|
||||||
|
|
||||||
// Add an artifacts list element to the root element.
|
// Add an artifacts list element to the root element.
|
||||||
Element artifactsListElement = doc.createElement(ExternalResultsXML.ARTIFACTS_LIST_ELEM.toString());
|
Element artifactsListElement = doc.createElement(ExternalResultsXMLParser.TagNames.ARTIFACTS_LIST_ELEM.toString());
|
||||||
rootElement.appendChild(artifactsListElement);
|
rootElement.appendChild(artifactsListElement);
|
||||||
|
|
||||||
// Add an artifact element to the artifacts list element. A standard
|
// Add an artifact element to the artifacts list element. A standard
|
||||||
// artifact type is used as the required type attribute of this
|
// artifact type is used as the required type attribute of this
|
||||||
// artifact element.
|
// artifact element.
|
||||||
Element artifactElement = doc.createElement(ExternalResultsXML.ARTIFACT_ELEM.toString());
|
Element artifactElement = doc.createElement(ExternalResultsXMLParser.TagNames.ARTIFACT_ELEM.toString());
|
||||||
artifactElement.setAttribute(ExternalResultsXML.TYPE_ATTR.toString(), ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getLabel());
|
artifactElement.setAttribute(ExternalResultsXMLParser.TagNames.TYPE_ATTR.toString(), ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getLabel());
|
||||||
artifactsListElement.appendChild(artifactElement);
|
artifactsListElement.appendChild(artifactElement);
|
||||||
|
|
||||||
// Add an optional file element to the artifact element, and add a path
|
// Add an optional file element to the artifact element, and add a path
|
||||||
@ -183,61 +188,61 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM
|
|||||||
// artifact is usually specified. If an artifact element has no file
|
// artifact is usually specified. If an artifact element has no file
|
||||||
// element, the data source is used as the default source file for the
|
// element, the data source is used as the default source file for the
|
||||||
// artifact.
|
// artifact.
|
||||||
Element fileElement = doc.createElement(ExternalResultsXML.SOURCE_FILE_ELEM.toString());
|
Element fileElement = doc.createElement(ExternalResultsXMLParser.TagNames.SOURCE_FILE_ELEM.toString());
|
||||||
artifactElement.appendChild(fileElement);
|
artifactElement.appendChild(fileElement);
|
||||||
Element pathElement = doc.createElement(ExternalResultsXML.PATH_ELEM.toString());
|
Element pathElement = doc.createElement(ExternalResultsXMLParser.TagNames.PATH_ELEM.toString());
|
||||||
pathElement.setTextContent(dataSourcePath);
|
pathElement.setTextContent(dataSourcePath);
|
||||||
fileElement.appendChild(pathElement);
|
fileElement.appendChild(pathElement);
|
||||||
|
|
||||||
// Add an artifact attribute element to the artifact element. A standard
|
// Add an artifact attribute element to the artifact element. A standard
|
||||||
// artifact attribute type is used as the required type XML attribute of
|
// artifact attribute type is used as the required type XML attribute of
|
||||||
// the artifact attribute element.
|
// the artifact attribute element.
|
||||||
Element artifactAttrElement = doc.createElement(ExternalResultsXML.ATTRIBUTE_ELEM.toString());
|
Element artifactAttrElement = doc.createElement(ExternalResultsXMLParser.TagNames.ATTRIBUTE_ELEM.toString());
|
||||||
artifactAttrElement.setAttribute(ExternalResultsXML.TYPE_ATTR.toString(), ATTRIBUTE_TYPE.TSK_SET_NAME.getLabel());
|
artifactAttrElement.setAttribute(ExternalResultsXMLParser.TagNames.TYPE_ATTR.toString(), ATTRIBUTE_TYPE.TSK_SET_NAME.getLabel());
|
||||||
artifactElement.appendChild(artifactAttrElement);
|
artifactElement.appendChild(artifactAttrElement);
|
||||||
|
|
||||||
// Add the required value element to the artifact attribute element,
|
// Add the required value element to the artifact attribute element,
|
||||||
// with an optional type XML attribute of ExternalXML.VALUE_TYPE_TEXT,
|
// with an optional type XML attribute of ExternalXML.VALUE_TYPE_TEXT,
|
||||||
// which is the default.
|
// which is the default.
|
||||||
Element artifactAttributeValueElement = doc.createElement(ExternalResultsXML.VALUE_ELEM.toString());
|
Element artifactAttributeValueElement = doc.createElement(ExternalResultsXMLParser.TagNames.VALUE_ELEM.toString());
|
||||||
artifactAttributeValueElement.setTextContent("SampleInterestingFilesSet");
|
artifactAttributeValueElement.setTextContent("SampleInterestingFilesSet");
|
||||||
artifactAttrElement.appendChild(artifactAttributeValueElement);
|
artifactAttrElement.appendChild(artifactAttributeValueElement);
|
||||||
|
|
||||||
// Add an optional source module element to the artifct attribute
|
// Add an optional source module element to the artifct attribute
|
||||||
// element.
|
// element.
|
||||||
Element artifactAttrSourceElement = doc.createElement(ExternalResultsXML.SOURCE_MODULE_ELEM.toString());
|
Element artifactAttrSourceElement = doc.createElement(ExternalResultsXMLParser.TagNames.SOURCE_MODULE_ELEM.toString());
|
||||||
artifactAttrSourceElement.setTextContent(moduleName);
|
artifactAttrSourceElement.setTextContent(moduleName);
|
||||||
artifactAttrElement.appendChild(artifactAttrSourceElement);
|
artifactAttrElement.appendChild(artifactAttrSourceElement);
|
||||||
|
|
||||||
// Add an artifact element with a user-defined type. No file element is
|
// Add an artifact element with a user-defined type. No file element is
|
||||||
// added to the artifact element, so the data source will be used as the
|
// added to the artifact element, so the data source will be used as the
|
||||||
// default for the source file.
|
// default for the source file.
|
||||||
artifactElement = doc.createElement(ExternalResultsXML.ARTIFACT_ELEM.toString());
|
artifactElement = doc.createElement(ExternalResultsXMLParser.TagNames.ARTIFACT_ELEM.toString());
|
||||||
artifactElement.setAttribute(ExternalResultsXML.TYPE_ATTR.toString(), "SampleArtifactType");
|
artifactElement.setAttribute(ExternalResultsXMLParser.TagNames.TYPE_ATTR.toString(), "SampleArtifactType");
|
||||||
artifactsListElement.appendChild(artifactElement);
|
artifactsListElement.appendChild(artifactElement);
|
||||||
|
|
||||||
// Add artifact attribute elements with user-defined types to the
|
// Add artifact attribute elements with user-defined types to the
|
||||||
// artifact element, adding value elements of assorted types.
|
// artifact element, adding value elements of assorted types.
|
||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
artifactAttrElement = doc.createElement(ExternalResultsXML.ATTRIBUTE_ELEM.toString());
|
artifactAttrElement = doc.createElement(ExternalResultsXMLParser.TagNames.ATTRIBUTE_ELEM.toString());
|
||||||
artifactAttrElement.setAttribute(ExternalResultsXML.TYPE_ATTR.toString(), "SampleArtifactAttributeType");
|
artifactAttrElement.setAttribute(ExternalResultsXMLParser.TagNames.TYPE_ATTR.toString(), "SampleArtifactAttributeType");
|
||||||
artifactElement.appendChild(artifactAttrElement);
|
artifactElement.appendChild(artifactAttrElement);
|
||||||
artifactAttributeValueElement = doc.createElement(ExternalResultsXML.VALUE_ELEM.toString());
|
artifactAttributeValueElement = doc.createElement(ExternalResultsXMLParser.TagNames.VALUE_ELEM.toString());
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
artifactAttributeValueElement.setAttribute(ExternalResultsXML.TYPE_ATTR.toString(), ExternalResultsXML.VALUE_TYPE_TEXT.toString());
|
artifactAttributeValueElement.setAttribute(ExternalResultsXMLParser.TagNames.TYPE_ATTR.toString(), ExternalResultsXMLParser.TagNames.VALUE_TYPE_TEXT.toString());
|
||||||
artifactAttributeValueElement.setTextContent("One");
|
artifactAttributeValueElement.setTextContent("One");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
artifactAttributeValueElement.setAttribute(ExternalResultsXML.TYPE_ATTR.toString(), ExternalResultsXML.VALUE_TYPE_INT32.toString());
|
artifactAttributeValueElement.setAttribute(ExternalResultsXMLParser.TagNames.TYPE_ATTR.toString(), ExternalResultsXMLParser.TagNames.VALUE_TYPE_INT32.toString());
|
||||||
artifactAttributeValueElement.setTextContent("2");
|
artifactAttributeValueElement.setTextContent("2");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
artifactAttributeValueElement.setAttribute(ExternalResultsXML.TYPE_ATTR.toString(), ExternalResultsXML.VALUE_TYPE_INT64.toString());
|
artifactAttributeValueElement.setAttribute(ExternalResultsXMLParser.TagNames.TYPE_ATTR.toString(), ExternalResultsXMLParser.TagNames.VALUE_TYPE_INT64.toString());
|
||||||
artifactAttributeValueElement.setTextContent("3");
|
artifactAttributeValueElement.setTextContent("3");
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
artifactAttributeValueElement.setAttribute(ExternalResultsXML.TYPE_ATTR.toString(), ExternalResultsXML.VALUE_TYPE_DOUBLE.toString());
|
artifactAttributeValueElement.setAttribute(ExternalResultsXMLParser.TagNames.TYPE_ATTR.toString(), ExternalResultsXMLParser.TagNames.VALUE_TYPE_DOUBLE.toString());
|
||||||
artifactAttributeValueElement.setTextContent("4.0");
|
artifactAttributeValueElement.setTextContent("4.0");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -245,25 +250,25 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add a reports list element to the root element.
|
// Add a reports list element to the root element.
|
||||||
Element reportsListElement = doc.createElement(ExternalResultsXML.REPORTS_LIST_ELEM.toString());
|
Element reportsListElement = doc.createElement(ExternalResultsXMLParser.TagNames.REPORTS_LIST_ELEM.toString());
|
||||||
rootElement.appendChild(reportsListElement);
|
rootElement.appendChild(reportsListElement);
|
||||||
|
|
||||||
// Add a report element to the reports list element.
|
// Add a report element to the reports list element.
|
||||||
Element reportElement = doc.createElement(ExternalResultsXML.REPORT_ELEM.toString());
|
Element reportElement = doc.createElement(ExternalResultsXMLParser.TagNames.REPORT_ELEM.toString());
|
||||||
reportsListElement.appendChild(reportElement);
|
reportsListElement.appendChild(reportElement);
|
||||||
|
|
||||||
// Add the required display name element to the report element.
|
// Add the required display name element to the report element.
|
||||||
Element reportDisplayNameElement = doc.createElement(ExternalResultsXML.DISPLAY_NAME_ELEM.toString());
|
Element reportDisplayNameElement = doc.createElement(ExternalResultsXMLParser.TagNames.DISPLAY_NAME_ELEM.toString());
|
||||||
reportDisplayNameElement.setTextContent("Sample Report");
|
reportDisplayNameElement.setTextContent("Sample Report");
|
||||||
reportElement.appendChild(reportDisplayNameElement);
|
reportElement.appendChild(reportDisplayNameElement);
|
||||||
|
|
||||||
// Add the required local path element to the report element.
|
// Add the required local path element to the report element.
|
||||||
Element reportPathElement = doc.createElement(ExternalResultsXML.LOCAL_PATH_ELEM.toString());
|
Element reportPathElement = doc.createElement(ExternalResultsXMLParser.TagNames.LOCAL_PATH_ELEM.toString());
|
||||||
reportPathElement.setTextContent(reportPath);
|
reportPathElement.setTextContent(reportPath);
|
||||||
reportElement.appendChild(reportPathElement);
|
reportElement.appendChild(reportPathElement);
|
||||||
|
|
||||||
// Add a derived files list element to the root element.
|
// Add a derived files list element to the root element.
|
||||||
Element derivedFilesListElement = doc.createElement(ExternalResultsXML.DERIVED_FILES_LIST_ELEM.toString());
|
Element derivedFilesListElement = doc.createElement(ExternalResultsXMLParser.TagNames.DERIVED_FILES_LIST_ELEM.toString());
|
||||||
rootElement.appendChild(derivedFilesListElement);
|
rootElement.appendChild(derivedFilesListElement);
|
||||||
|
|
||||||
// Add derived file elements to the derived files list element. Each
|
// Add derived file elements to the derived files list element. Each
|
||||||
@ -273,13 +278,13 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM
|
|||||||
// parent.
|
// parent.
|
||||||
Element parentPathElement = null;
|
Element parentPathElement = null;
|
||||||
for (String filePath : derivedFilePaths) {
|
for (String filePath : derivedFilePaths) {
|
||||||
Element derivedFileElement = doc.createElement(ExternalResultsXML.DERIVED_FILE_ELEM.toString());
|
Element derivedFileElement = doc.createElement(ExternalResultsXMLParser.TagNames.DERIVED_FILE_ELEM.toString());
|
||||||
derivedFilesListElement.appendChild(derivedFileElement);
|
derivedFilesListElement.appendChild(derivedFileElement);
|
||||||
Element localPathElement = doc.createElement(ExternalResultsXML.LOCAL_PATH_ELEM.toString());
|
Element localPathElement = doc.createElement(ExternalResultsXMLParser.TagNames.LOCAL_PATH_ELEM.toString());
|
||||||
localPathElement.setTextContent(filePath);
|
localPathElement.setTextContent(filePath);
|
||||||
derivedFileElement.appendChild(localPathElement);
|
derivedFileElement.appendChild(localPathElement);
|
||||||
if (parentPathElement == null) {
|
if (parentPathElement == null) {
|
||||||
parentPathElement = doc.createElement(ExternalResultsXML.PARENT_PATH_ELEM.toString());
|
parentPathElement = doc.createElement(ExternalResultsXMLParser.TagNames.PARENT_PATH_ELEM.toString());
|
||||||
parentPathElement.setTextContent(dataSourcePath);
|
parentPathElement.setTextContent(dataSourcePath);
|
||||||
derivedFileElement.appendChild(parentPathElement);
|
derivedFileElement.appendChild(parentPathElement);
|
||||||
}
|
}
|
||||||
|
@ -23,10 +23,12 @@ import java.nio.file.Path;
|
|||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ErrorInfo;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestServices;
|
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||||
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
|
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
|
||||||
@ -36,232 +38,165 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
|
|||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.DerivedFile;
|
import org.sleuthkit.datamodel.DerivedFile;
|
||||||
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mechanism to import blackboard items, derived files, etc. It is decoupled
|
* Uses a standard representation of results data (e.g., artifacts, derived
|
||||||
* from the actual parsing/interfacing with external data.
|
* files, reports) to import results generated by a process external to Autopsy
|
||||||
|
* into Autopsy.
|
||||||
*/
|
*/
|
||||||
public class ExternalResultsImporter {
|
public final class ExternalResultsImporter {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ExternalResultsImporter.class.getName());
|
private static final Logger logger = Logger.getLogger(ExternalResultsImporter.class.getName());
|
||||||
private static final String EVENT_STRING = "External Results";
|
private final List<ErrorInfo> errors = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Import results for a data source from an XML localFile (see
|
* Import results generated by a process external to Autopsy into Autopsy.
|
||||||
* org.sleuthkit.autopsy.externalresults.autopsy_external_results.xsd).
|
|
||||||
*
|
*
|
||||||
* @param dataSource A data source.
|
* @param results A standard representation of results data (e.g.,
|
||||||
* @param resultsXmlPath Path to an XML localFile containing results (e.g.,
|
* artifacts, derived files, reports)from the data source.
|
||||||
* blackboard artifacts, derived files, reports) from the data source.
|
* @return A collection of error messages, possibly empty. The error
|
||||||
|
* messages are already logged but are provided to allow the caller to
|
||||||
|
* provide additional user feedback via the Autopsy user interface.
|
||||||
*/
|
*/
|
||||||
public static void importResultsFromXML(Content dataSource, String resultsXmlPath) { // RJCTODO: Return error messages
|
public List<ErrorInfo> importResults(ExternalResults results) {
|
||||||
ExternalResults results = new ExternalResultsXMLParser(dataSource, resultsXmlPath).parse(); // RJCTODO: Return error messages
|
// Import files first, they may be artifactData sources.
|
||||||
// RJCTODO: Get external results, restore ExternalResults parser interface
|
importDerivedFiles(results);
|
||||||
importDerivedFiles(results); // Import files first, they may be artifact sources.
|
importArtifacts(results);
|
||||||
importArtifacts(dataSource, results);
|
|
||||||
importReports(results);
|
importReports(results);
|
||||||
//
|
return Collections.unmodifiableList(this.errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void importDerivedFiles(ExternalResults results) {
|
private void importDerivedFiles(ExternalResults results) {
|
||||||
FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
|
FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
|
||||||
for (ExternalResults.DerivedFile fileData : results.getDerivedFiles()) {
|
for (ExternalResults.DerivedFile fileData : results.getDerivedFiles()) {
|
||||||
|
String filePath = Case.getCurrentCase().getCaseDirectory() + File.separator + fileData.getLocalPath();
|
||||||
try {
|
try {
|
||||||
String localPath = fileData.getLocalPath();
|
File localFile = new File(filePath);
|
||||||
File localFile = new File(localPath); // RJCTODO: State/check ExternalResults contract that is not empty
|
|
||||||
if (!localFile.exists()) {
|
if (!localFile.exists()) {
|
||||||
AbstractFile parentFile = findFileInDatabase(fileData.getParentPath());
|
AbstractFile parentFile = findFile(results.getDataSource(), fileData.getParentPath());
|
||||||
if (parentFile == null) {
|
if (parentFile != null) {
|
||||||
String relativePath = getPathRelativeToCaseFolder(fileData.getLocalPath());
|
DerivedFile derivedFile = fileManager.addDerivedFile(localFile.getName(), fileData.getLocalPath(), localFile.length(),
|
||||||
DerivedFile derivedFile = fileManager.addDerivedFile(localFile.getName(), relativePath, localFile.length(),
|
0, 0, 0, 0, // Do not currently have file times for derived files from external processes.
|
||||||
0, 0, 0, 0, // Do not currently have localFile times for derived files, should they provide via XML?
|
true, parentFile,
|
||||||
true, parentFile, "", "", "", "");
|
"", "", "", ""); // Not currently providing derivation info for derived files from external processes.
|
||||||
|
|
||||||
if (derivedFile != null) {
|
|
||||||
IngestServices.getInstance().fireModuleContentEvent(new ModuleContentEvent(derivedFile));
|
IngestServices.getInstance().fireModuleContentEvent(new ModuleContentEvent(derivedFile));
|
||||||
|
} else {
|
||||||
|
String errorMessage = String.format("Could not import derived file at %s, parent file %s not found", filePath);
|
||||||
|
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage);
|
||||||
|
this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// RJCTODO: parent file not in database
|
String errorMessage = String.format("Could not import derived file at %s, file does not exist", filePath);
|
||||||
}
|
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage);
|
||||||
} else {
|
this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage));
|
||||||
// RJCTODO: file missing
|
|
||||||
}
|
}
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.SEVERE, ex.getLocalizedMessage());
|
String errorMessage = String.format("Could not import derived file at %s, error querying/updating case database", filePath);
|
||||||
|
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage, ex);
|
||||||
|
this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage, ex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void importArtifacts(ExternalResults results) {
|
||||||
* Create and add new blackboard artifacts, attributes, and types
|
SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase();
|
||||||
*
|
for (ExternalResults.Artifact artifactData : results.getArtifacts()) {
|
||||||
* @param results
|
|
||||||
* @param dataSource
|
|
||||||
*/
|
|
||||||
private static void importArtifacts(Content dataSource, ExternalResults results) {
|
|
||||||
for (ExternalResults.Artifact art : results.getArtifacts()) {
|
|
||||||
try {
|
try {
|
||||||
// Get the artifact type id if defined, or create a new
|
// Add the artifact to the case database.
|
||||||
// user-defined artifact type.
|
boolean artifactTypeIsUserDefined = false;
|
||||||
int artifactTypeId;
|
int artifactTypeId = caseDb.getArtifactTypeIdIfExists(artifactData.getType());
|
||||||
BlackboardArtifact.ARTIFACT_TYPE stdArtType = isStandardArtifactType(art.getType());
|
if (artifactTypeId == -1) {
|
||||||
if (stdArtType != null) {
|
artifactTypeId = caseDb.addArtifactType(artifactData.getType(), artifactData.getType());
|
||||||
artifactTypeId = stdArtType.getTypeID();
|
artifactTypeIsUserDefined = true;
|
||||||
} else {
|
|
||||||
artifactTypeId = Case.getCurrentCase().getSleuthkitCase().addArtifactType(art.getType(), art.getType());
|
|
||||||
}
|
}
|
||||||
|
Content sourceFile = findFile(results.getDataSource(), artifactData.getSourceFilePath());
|
||||||
|
BlackboardArtifact artifact = sourceFile.newArtifact(artifactTypeId);
|
||||||
|
|
||||||
Collection<BlackboardAttribute> bbAttributes = new ArrayList<>();
|
// Add the artifact's attributes to the case database.
|
||||||
for (ExternalResults.ArtifactAttribute attr : art.getAttributes()) {
|
Collection<BlackboardAttribute> attributes = new ArrayList<>();
|
||||||
int bbAttrTypeId;
|
for (ExternalResults.ArtifactAttribute attributeData : artifactData.getAttributes()) {
|
||||||
BlackboardAttribute.ATTRIBUTE_TYPE stdAttrType = isStandardAttributeType(attr.getType());
|
int attributeTypeId = caseDb.getAttrTypeIdIfExists(attributeData.getType());
|
||||||
if (stdAttrType != null) {
|
if (artifactTypeId == -1) {
|
||||||
bbAttrTypeId = stdAttrType.getTypeID();
|
artifactTypeId = caseDb.addArtifactType(attributeData.getType(), attributeData.getType());
|
||||||
} else {
|
|
||||||
// assume it's user defined RJCTODO fix
|
|
||||||
bbAttrTypeId = Case.getCurrentCase().getSleuthkitCase().addAttrType(attr.getType(), attr.getType());
|
|
||||||
}
|
}
|
||||||
|
switch (attributeData.getValueType()) {
|
||||||
BlackboardAttribute bbAttr = null;
|
|
||||||
switch (attr.getValueType()) {
|
|
||||||
case "text": //NON-NLS
|
case "text": //NON-NLS
|
||||||
bbAttr = new BlackboardAttribute(bbAttrTypeId, attr.getSourceModule(), attr.getValue());
|
attributes.add(new BlackboardAttribute(attributeTypeId, attributeData.getSourceModule(), attributeData.getValue()));
|
||||||
break;
|
break;
|
||||||
case "int32": //NON-NLS
|
case "int32": //NON-NLS
|
||||||
int intValue = Integer.parseInt(attr.getValue());
|
int intValue = Integer.parseInt(attributeData.getValue());
|
||||||
bbAttr = new BlackboardAttribute(bbAttrTypeId, attr.getSourceModule(), intValue);
|
attributes.add(new BlackboardAttribute(attributeTypeId, attributeData.getSourceModule(), intValue));
|
||||||
break;
|
break;
|
||||||
case "int64": //NON-NLS
|
case "int64": //NON-NLS
|
||||||
long longValue = Long.parseLong(attr.getValue());
|
long longValue = Long.parseLong(attributeData.getValue());
|
||||||
bbAttr = new BlackboardAttribute(bbAttrTypeId, attr.getSourceModule(), longValue);
|
attributes.add(new BlackboardAttribute(attributeTypeId, attributeData.getSourceModule(), longValue));
|
||||||
break;
|
break;
|
||||||
case "double": //NON-NLS
|
case "double": //NON-NLS
|
||||||
double doubleValue = Double.parseDouble(attr.getValue());
|
double doubleValue = Double.parseDouble(attributeData.getValue());
|
||||||
bbAttr = new BlackboardAttribute(bbAttrTypeId, attr.getSourceModule(), doubleValue);
|
attributes.add(new BlackboardAttribute(attributeTypeId, attributeData.getSourceModule(), doubleValue));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.log(Level.WARNING, "Ignoring invalid attribute value type {0}", attr.getValueType());
|
String errorMessage = String.format("Could not import %s attribute, value = %s, for %s artifact from %s, unrecognized attribute value type: %s",
|
||||||
|
attributeData.getType(), attributeData.getValue(),
|
||||||
|
artifactData.getType(), artifactData.getSourceFilePath(),
|
||||||
|
attributeData.getValueType());
|
||||||
|
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage);
|
||||||
|
this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (bbAttr != null) {
|
|
||||||
bbAttributes.add(bbAttr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
artifact.addAttributes(attributes);
|
||||||
|
|
||||||
// Get associated localFile (if any) to use as the content obj to attach the artifact to
|
if (!artifactTypeIsUserDefined) {
|
||||||
Content currContent = null;
|
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(this.getClass().getSimpleName(), BlackboardArtifact.ARTIFACT_TYPE.fromID(artifactTypeId)));
|
||||||
if (art.getSourceFilePath().isEmpty()) {
|
|
||||||
currContent = findFileInDatabase(art.getSourceFilePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no associated localFile, use current data source itself
|
|
||||||
if (currContent == null) {
|
|
||||||
currContent = dataSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlackboardArtifact bbArt = currContent.newArtifact(artifactTypeId);
|
|
||||||
bbArt.addAttributes(bbAttributes);
|
|
||||||
if (stdArtType != null) {
|
|
||||||
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent("", stdArtType)); //NON-NLS
|
|
||||||
}
|
}
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.SEVERE, ex.getLocalizedMessage());
|
String errorMessage = String.format("Could not import %s artifact from %s, error updating case database", artifactData.getType(), artifactData.getSourceFilePath());
|
||||||
|
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage, ex);
|
||||||
|
this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage, ex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void importReports(ExternalResults results) {
|
private void importReports(ExternalResults results) {
|
||||||
for (ExternalResults.Report report : results.getReports()) {
|
for (ExternalResults.Report report : results.getReports()) {
|
||||||
|
String reportPath = Case.getCurrentCase().getCaseDirectory() + File.separator + report.getLocalPath();
|
||||||
try {
|
try {
|
||||||
String reportPath = report.getLocalPath();
|
|
||||||
File reportFile = new File(reportPath);
|
File reportFile = new File(reportPath);
|
||||||
if (reportFile.exists()) {
|
if (reportFile.exists()) {
|
||||||
// Try to get a relative local path
|
Case.getCurrentCase().getSleuthkitCase().addReport(reportPath, report.getDisplayName());
|
||||||
String relPath = reportPath;
|
} else {
|
||||||
Path pathTo = Paths.get(reportPath);
|
String errorMessage = String.format("Could not import report at %s, file does not exist", reportPath);
|
||||||
if (pathTo.isAbsolute()) {
|
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage);
|
||||||
Path pathBase = Paths.get(Case.getCurrentCase().getCaseDirectory());
|
this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage));
|
||||||
try {
|
|
||||||
Path pathRelative = pathBase.relativize(pathTo);
|
|
||||||
relPath = pathRelative.toString();
|
|
||||||
} catch (IllegalArgumentException ex) {
|
|
||||||
logger.log(Level.WARNING, "Report file {0} path may be incorrect. The report record will still be added to the database.", reportPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!relPath.isEmpty()) {
|
|
||||||
Case.getCurrentCase().getSleuthkitCase().addReport(relPath, report.getDisplayName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.SEVERE, ex.getLocalizedMessage());
|
String errorMessage = String.format("Could not import report at %s, error updating case database", reportPath);
|
||||||
|
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage, ex);
|
||||||
|
this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage, ex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private AbstractFile findFile(Content dataSource, String filePath) throws TskCoreException {
|
||||||
* util function
|
AbstractFile file = null;
|
||||||
*
|
Path path = Paths.get(filePath);
|
||||||
* @param filePath full path including localFile or dir name
|
|
||||||
* @return AbstractFile
|
|
||||||
* @throws TskCoreException
|
|
||||||
*/
|
|
||||||
private static AbstractFile findFileInDatabase(String filePath) throws TskCoreException {
|
|
||||||
AbstractFile abstractFile = null;
|
|
||||||
String fileName = filePath;
|
|
||||||
String parentPath = "";
|
|
||||||
int charPos = filePath.lastIndexOf("/");
|
|
||||||
if (charPos >= 0) {
|
|
||||||
fileName = filePath.substring(charPos + 1);
|
|
||||||
parentPath = filePath.substring(0, charPos + 1);
|
|
||||||
}
|
|
||||||
String whereQuery = "name='" + fileName + "' AND parent_path='" + parentPath + "'"; //NON-NLS
|
|
||||||
List<AbstractFile> files = Case.getCurrentCase().getSleuthkitCase().findAllFilesWhere(whereQuery);
|
|
||||||
if (files.size() > 0) {
|
|
||||||
abstractFile = files.get(0);
|
|
||||||
if (files.size() > 1) {
|
|
||||||
logger.log(Level.WARNING, "Ignoring extra files found for path {0}", filePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return abstractFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getPathRelativeToCaseFolder(String localPath) {
|
|
||||||
String relativePath = "";
|
|
||||||
Path path = Paths.get(localPath);
|
|
||||||
if (path.isAbsolute()) {
|
if (path.isAbsolute()) {
|
||||||
Path pathBase = Paths.get(Case.getCurrentCase().getCaseDirectory());
|
FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
|
||||||
try {
|
List<AbstractFile> files = fileManager.openFiles(dataSource, filePath);
|
||||||
Path pathRelative = pathBase.relativize(path);
|
if (files.size() > 0) {
|
||||||
relativePath = pathRelative.toString();
|
file = files.get(0);
|
||||||
} catch (IllegalArgumentException ex) {
|
if (files.size() > 1) {
|
||||||
// RJCTODO: Fix this
|
String errorMessage = String.format("Ambiguous file path: %s", filePath);
|
||||||
logger.log(Level.WARNING, "Report file {0} path may be incorrect. The report record will still be added to the database.", localPath);
|
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage);
|
||||||
|
this.errors.add(new ErrorInfo(this.getClass().getName(), errorMessage));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// RJCTODO: Path is not absolute
|
// RJCTODO: Need a look up that goes for relative path
|
||||||
}
|
}
|
||||||
return relativePath;
|
return file;
|
||||||
}
|
|
||||||
|
|
||||||
private static BlackboardArtifact.ARTIFACT_TYPE isStandardArtifactType(String artTypeStr) {
|
|
||||||
BlackboardArtifact.ARTIFACT_TYPE[] stdArts = BlackboardArtifact.ARTIFACT_TYPE.values();
|
|
||||||
for (BlackboardArtifact.ARTIFACT_TYPE art : stdArts) {
|
|
||||||
if (art.getLabel().equals(artTypeStr)) {
|
|
||||||
return art;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static BlackboardAttribute.ATTRIBUTE_TYPE isStandardAttributeType(String attrTypeStr) {
|
|
||||||
BlackboardAttribute.ATTRIBUTE_TYPE[] stdAttrs = BlackboardAttribute.ATTRIBUTE_TYPE.values();
|
|
||||||
for (BlackboardAttribute.ATTRIBUTE_TYPE attr : stdAttrs) {
|
|
||||||
if (attr.getLabel().equals(attrTypeStr)) {
|
|
||||||
return attr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,12 @@
|
|||||||
package org.sleuthkit.autopsy.externalresults;
|
package org.sleuthkit.autopsy.externalresults;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ErrorInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for parsers that convert some representation of results data (
|
* Interface for parsers that convert some representation of results data (e.g.,
|
||||||
* e.g., artifacts, derived files, reports) generated by a process external to
|
* artifacts, derived files, reports) generated by a process external to Autopsy
|
||||||
* Autopsy into a form ready for import into Autopsy.
|
* into a form ready for import into Autopsy.
|
||||||
*/
|
*/
|
||||||
public interface ExternalResultsParser {
|
public interface ExternalResultsParser {
|
||||||
|
|
||||||
@ -32,15 +33,17 @@ public interface ExternalResultsParser {
|
|||||||
* external to Autopsy and supplied to the parser via its constructor into a
|
* external to Autopsy and supplied to the parser via its constructor into a
|
||||||
* form ready for import into Autopsy.
|
* form ready for import into Autopsy.
|
||||||
*
|
*
|
||||||
* @return Results data in a form ready for import into Autopsy.
|
* @return External results data in a form ready for import into Autopsy.
|
||||||
*/
|
*/
|
||||||
ExternalResults parse(); // RJCTODO: May need to add data source arg
|
ExternalResults parse(); // RJCTODO: May need to add data source arg
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets error messages describing any errors encountered while parsing the
|
* Gets error information describing any errors encountered while parsing
|
||||||
* input results representation.
|
* the input results representation.
|
||||||
*
|
*
|
||||||
* @return A possibly empty collection of error message strings.
|
* @return A collection of error messages, possibly empty. The error
|
||||||
|
* messages are already logged but are provided to allow the caller to
|
||||||
|
* provide additional user feedback via the Autopsy user interface.
|
||||||
*/
|
*/
|
||||||
List<String> getErrorMessages();
|
List<ErrorInfo> getErrorInfo();
|
||||||
}
|
}
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* Autopsy Forensic Browser
|
|
||||||
*
|
|
||||||
* Copyright 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.externalresults;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tags for an external results XML file.
|
|
||||||
*/
|
|
||||||
public enum ExternalResultsXML {
|
|
||||||
ROOT_ELEM("autopsy_results"), //NON-NLS
|
|
||||||
ARTIFACTS_LIST_ELEM("artifacts"), //NON-NLS
|
|
||||||
ARTIFACT_ELEM("artifact"), //NON-NLS
|
|
||||||
SOURCE_FILE_ELEM("source_file"), //NON-NLS
|
|
||||||
PATH_ELEM("path"), //NON-NLS
|
|
||||||
ATTRIBUTE_ELEM("attribute"), //NON-NLS
|
|
||||||
VALUE_ELEM("value"), //NON-NLS
|
|
||||||
SOURCE_MODULE_ELEM("source_module"), //NON-NLS
|
|
||||||
REPORTS_LIST_ELEM("reports"), //NON-NLS
|
|
||||||
REPORT_ELEM("report"), //NON-NLS
|
|
||||||
DISPLAY_NAME_ELEM("display_name"), //NON-NLS
|
|
||||||
LOCAL_PATH_ELEM("local_path"), //NON-NLS
|
|
||||||
DERIVED_FILES_LIST_ELEM("derived_files"), //NON-NLS
|
|
||||||
DERIVED_FILE_ELEM("derived_file"), //NON-NLS
|
|
||||||
PARENT_PATH_ELEM("parent_path"), //NON-NLS
|
|
||||||
TYPE_ATTR("type"), //NON-NLS
|
|
||||||
NAME_ATTR("name"), //NON-NLS
|
|
||||||
VALUE_TYPE_TEXT("text"),
|
|
||||||
VALUE_TYPE_INT32("int32"),
|
|
||||||
VALUE_TYPE_INT64("int64"),
|
|
||||||
VALUE_TYPE_DOUBLE("double");
|
|
||||||
|
|
||||||
private final String text;
|
|
||||||
|
|
||||||
private ExternalResultsXML(final String text) {
|
|
||||||
this.text = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
}
|
|
@ -18,9 +18,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.externalresults;
|
package org.sleuthkit.autopsy.externalresults;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.ErrorInfo;
|
||||||
import org.sleuthkit.autopsy.coreutils.XMLUtil;
|
import org.sleuthkit.autopsy.coreutils.XMLUtil;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
@ -28,8 +31,8 @@ import org.w3c.dom.Element;
|
|||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses an XML representation of externally generated results (artifacts,
|
* Parses an XML representation of of results data (e.g., artifacts, derived
|
||||||
* derived files, and reports).
|
* files, reports) generated by a process external to Autopsy into Autopsy.
|
||||||
*/
|
*/
|
||||||
public final class ExternalResultsXMLParser implements ExternalResultsParser {
|
public final class ExternalResultsXMLParser implements ExternalResultsParser {
|
||||||
|
|
||||||
@ -37,13 +40,52 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
|
|||||||
private static final String XSD_FILE = "autopsy_external_results.xsd"; //NON-NLS
|
private static final String XSD_FILE = "autopsy_external_results.xsd"; //NON-NLS
|
||||||
private final String resultsFilePath;
|
private final String resultsFilePath;
|
||||||
private final ExternalResults externalResults;
|
private final ExternalResults externalResults;
|
||||||
|
private final List<ErrorInfo> errors = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tags for an external results XML file.
|
||||||
|
*/
|
||||||
|
public enum TagNames {
|
||||||
|
|
||||||
|
ROOT_ELEM("autopsy_results"), //NON-NLS
|
||||||
|
ARTIFACTS_LIST_ELEM("artifacts"), //NON-NLS
|
||||||
|
ARTIFACT_ELEM("artifact"), //NON-NLS
|
||||||
|
SOURCE_FILE_ELEM("source_file"), //NON-NLS
|
||||||
|
PATH_ELEM("path"), //NON-NLS
|
||||||
|
ATTRIBUTE_ELEM("attribute"), //NON-NLS
|
||||||
|
VALUE_ELEM("value"), //NON-NLS
|
||||||
|
SOURCE_MODULE_ELEM("source_module"), //NON-NLS
|
||||||
|
REPORTS_LIST_ELEM("reports"), //NON-NLS
|
||||||
|
REPORT_ELEM("report"), //NON-NLS
|
||||||
|
DISPLAY_NAME_ELEM("display_name"), //NON-NLS
|
||||||
|
LOCAL_PATH_ELEM("local_path"), //NON-NLS
|
||||||
|
DERIVED_FILES_LIST_ELEM("derived_files"), //NON-NLS
|
||||||
|
DERIVED_FILE_ELEM("derived_file"), //NON-NLS
|
||||||
|
PARENT_PATH_ELEM("parent_path"), //NON-NLS
|
||||||
|
TYPE_ATTR("type"), //NON-NLS
|
||||||
|
NAME_ATTR("name"), //NON-NLS
|
||||||
|
VALUE_TYPE_TEXT("text"),
|
||||||
|
VALUE_TYPE_INT32("int32"),
|
||||||
|
VALUE_TYPE_INT64("int64"),
|
||||||
|
VALUE_TYPE_DOUBLE("double");
|
||||||
|
private final String text;
|
||||||
|
|
||||||
|
private TagNames(final String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param importFilePath Full path of the results file to be parsed.
|
* @param importFilePath Full path of the results file to be parsed.
|
||||||
*/
|
*/
|
||||||
ExternalResultsXMLParser(Content dataSource, String resultsFilePath) {
|
public ExternalResultsXMLParser(Content dataSource, String resultsFilePath) {
|
||||||
this.resultsFilePath = resultsFilePath;
|
this.resultsFilePath = resultsFilePath;
|
||||||
externalResults = new ExternalResults(dataSource);
|
externalResults = new ExternalResults(dataSource);
|
||||||
}
|
}
|
||||||
@ -59,38 +101,57 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
|
|||||||
final Document doc = XMLUtil.loadDoc(ExternalResultsXMLParser.class, this.resultsFilePath, XSD_FILE);
|
final Document doc = XMLUtil.loadDoc(ExternalResultsXMLParser.class, this.resultsFilePath, XSD_FILE);
|
||||||
if (doc != null) {
|
if (doc != null) {
|
||||||
final Element rootElem = doc.getDocumentElement();
|
final Element rootElem = doc.getDocumentElement();
|
||||||
if (rootElem != null && rootElem.getNodeName().equals(ExternalResultsXML.ROOT_ELEM.toString())) {
|
if (rootElem != null && rootElem.getNodeName().equals(TagNames.ROOT_ELEM.toString())) {
|
||||||
|
parseDerivedFiles(rootElem);
|
||||||
parseArtifacts(rootElem);
|
parseArtifacts(rootElem);
|
||||||
parseReports(rootElem);
|
parseReports(rootElem);
|
||||||
parseDerivedFiles(rootElem);
|
|
||||||
} else {
|
} else {
|
||||||
logger.log(Level.SEVERE, "Did not find {0} root element of {2}", new Object[]{
|
String errorMessage = String.format("Did not find %s root element of %s", TagNames.ROOT_ELEM.toString(), this.resultsFilePath);
|
||||||
ExternalResultsXML.ROOT_ELEM.toString(), this.resultsFilePath}); //NON-NLS
|
recordError(errorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception ex) {
|
||||||
logger.log(Level.SEVERE, "Error parsing " + this.resultsFilePath, e); //NON-NLS
|
String errorMessage = String.format("Error parsing %s", this.resultsFilePath);
|
||||||
|
recordError(errorMessage, ex);
|
||||||
}
|
}
|
||||||
return externalResults;
|
return externalResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getErrorMessages() {
|
public List<ErrorInfo> getErrorInfo() {
|
||||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
return Collections.unmodifiableList(this.errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseDerivedFiles(Element rootElement) {
|
||||||
|
NodeList derivedFilesListNodes = rootElement.getElementsByTagName(TagNames.DERIVED_FILES_LIST_ELEM.toString());
|
||||||
|
for (int i = 0; i < derivedFilesListNodes.getLength(); ++i) {
|
||||||
|
Element derivedFilesListElem = (Element) derivedFilesListNodes.item(i);
|
||||||
|
NodeList derivedFileNodes = derivedFilesListElem.getElementsByTagName(TagNames.DERIVED_FILE_ELEM.toString());
|
||||||
|
for (int j = 0; j < derivedFileNodes.getLength(); ++j) {
|
||||||
|
Element derivedFileElem = (Element) derivedFileNodes.item(j);
|
||||||
|
String path = getChildElementContent(derivedFileElem, TagNames.LOCAL_PATH_ELEM.toString());
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String parentPath = getChildElementContent((Element) derivedFileNodes.item(j), TagNames.PARENT_PATH_ELEM.toString());
|
||||||
|
if (parentPath.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
externalResults.addDerivedFile(path, parentPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseArtifacts(final Element root) {
|
private void parseArtifacts(final Element root) {
|
||||||
NodeList artifactsListNodes = root.getElementsByTagName(ExternalResultsXML.ARTIFACTS_LIST_ELEM.toString());
|
NodeList artifactsListNodes = root.getElementsByTagName(TagNames.ARTIFACTS_LIST_ELEM.toString());
|
||||||
for (int i = 0; i < artifactsListNodes.getLength(); ++i) {
|
for (int i = 0; i < artifactsListNodes.getLength(); ++i) {
|
||||||
Element artifactsListElem = (Element) artifactsListNodes.item(i);
|
Element artifactsListElem = (Element) artifactsListNodes.item(i);
|
||||||
NodeList artifactNodes = artifactsListElem.getElementsByTagName(ExternalResultsXML.ARTIFACT_ELEM.toString());
|
NodeList artifactNodes = artifactsListElem.getElementsByTagName(TagNames.ARTIFACT_ELEM.toString());
|
||||||
for (int j = 0; j < artifactNodes.getLength(); ++j) {
|
for (int j = 0; j < artifactNodes.getLength(); ++j) {
|
||||||
Element artifactElem = (Element) artifactNodes.item(j);
|
Element artifactElem = (Element) artifactNodes.item(j);
|
||||||
final String type = getElementAttributeValue(artifactElem, ExternalResultsXML.TYPE_ATTR.toString());
|
final String type = getElementAttributeValue(artifactElem, TagNames.TYPE_ATTR.toString());
|
||||||
if (!type.isEmpty()) {
|
if (!type.isEmpty()) {
|
||||||
Element sourceFileElem = getChildElement(artifactElem, ExternalResultsXML.SOURCE_FILE_ELEM.toString());
|
final String sourceFilePath = this.getChildElementContent((Element) artifactElem, TagNames.PATH_ELEM.toString());
|
||||||
if (sourceFileElem != null) {
|
|
||||||
final String sourceFilePath = this.getChildElementContent((Element) sourceFileElem, ExternalResultsXML.PATH_ELEM.toString());
|
|
||||||
if (!sourceFilePath.isEmpty()) {
|
if (!sourceFilePath.isEmpty()) {
|
||||||
ExternalResults.Artifact artifact = externalResults.addArtifact(type, sourceFilePath);
|
ExternalResults.Artifact artifact = externalResults.addArtifact(type, sourceFilePath);
|
||||||
parseArtifactAttributes(artifactElem, artifact);
|
parseArtifactAttributes(artifactElem, artifact);
|
||||||
@ -99,42 +160,41 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void parseArtifactAttributes(final Element artifactElem, ExternalResults.Artifact artifact) {
|
private void parseArtifactAttributes(final Element artifactElem, ExternalResults.Artifact artifact) {
|
||||||
NodeList attributeNodesList = artifactElem.getElementsByTagName(ExternalResultsXML.ATTRIBUTE_ELEM.toString());
|
NodeList attributeNodesList = artifactElem.getElementsByTagName(TagNames.ATTRIBUTE_ELEM.toString());
|
||||||
for (int i = 0; i < attributeNodesList.getLength(); ++i) {
|
for (int i = 0; i < attributeNodesList.getLength(); ++i) {
|
||||||
// Get the type of the artifact attribute.
|
// Get the type of the artifact attribute.
|
||||||
Element attributeElem = (Element) attributeNodesList.item(i);
|
Element attributeElem = (Element) attributeNodesList.item(i);
|
||||||
final String type = getElementAttributeValue(attributeElem, ExternalResultsXML.TYPE_ATTR.toString());
|
final String type = getElementAttributeValue(attributeElem, TagNames.TYPE_ATTR.toString());
|
||||||
if (type.isEmpty()) {
|
if (type.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Get the value of the artifact attribute.
|
// Get the value of the artifact attribute.
|
||||||
Element valueElem = this.getChildElement(attributeElem, ExternalResultsXML.VALUE_ELEM.toString());
|
Element valueElem = this.getChildElement(attributeElem, TagNames.VALUE_ELEM.toString());
|
||||||
if (valueElem == null) {
|
if (valueElem == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final String value = valueElem.getTextContent();
|
final String value = valueElem.getTextContent();
|
||||||
if (value.isEmpty()) {
|
if (value.isEmpty()) {
|
||||||
logger.log(Level.WARNING, "Found {0} element that has no content in {1}", new Object[]{
|
String errorMessage = String.format("Found %s element that has no content in %s",
|
||||||
ExternalResultsXML.VALUE_ELEM.toString(), this.resultsFilePath});
|
TagNames.VALUE_ELEM.toString(), this.resultsFilePath);
|
||||||
|
recordError(errorMessage);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Get the value type.
|
// Get the value type.
|
||||||
String valueType = valueElem.getAttribute(ExternalResultsXML.TYPE_ATTR.toString());
|
String valueType = valueElem.getAttribute(TagNames.TYPE_ATTR.toString());
|
||||||
if (valueType.isEmpty()) {
|
if (valueType.isEmpty()) {
|
||||||
valueType = ExternalResultsXML.VALUE_TYPE_TEXT.toString();
|
valueType = TagNames.VALUE_TYPE_TEXT.toString();
|
||||||
}
|
}
|
||||||
// Get the source module for the artifact attribute.
|
// Get the source module for the artifact attribute.
|
||||||
String sourceModule = "";
|
String sourceModule = "";
|
||||||
NodeList sourceModuleNodes = attributeElem.getElementsByTagName(ExternalResultsXML.SOURCE_MODULE_ELEM.toString());
|
NodeList sourceModuleNodes = attributeElem.getElementsByTagName(TagNames.SOURCE_MODULE_ELEM.toString());
|
||||||
if (sourceModuleNodes.getLength() > 0) {
|
if (sourceModuleNodes.getLength() > 0) {
|
||||||
if (sourceModuleNodes.getLength() > 1) {
|
if (sourceModuleNodes.getLength() > 1) {
|
||||||
logger.log(Level.WARNING, "Found multiple {0} child elements for {1} element in {2}, ignoring all but first occurrence", new Object[]{
|
String errorMessage = String.format("Found multiple %s child elements for %s element in %s, ignoring all but first occurrence",
|
||||||
ExternalResultsXML.SOURCE_MODULE_ELEM.toString(),
|
TagNames.SOURCE_MODULE_ELEM.toString(), attributeElem.getTagName(), this.resultsFilePath);
|
||||||
attributeElem.getTagName(),
|
recordError(errorMessage);
|
||||||
this.resultsFilePath}); // NON-NLS
|
|
||||||
}
|
}
|
||||||
Element srcModuleElem = (Element) sourceModuleNodes.item(0);
|
Element srcModuleElem = (Element) sourceModuleNodes.item(0);
|
||||||
sourceModule = srcModuleElem.getTextContent();
|
sourceModule = srcModuleElem.getTextContent();
|
||||||
@ -145,17 +205,17 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void parseReports(Element root) {
|
private void parseReports(Element root) {
|
||||||
NodeList reportsListNodes = root.getElementsByTagName(ExternalResultsXML.REPORTS_LIST_ELEM.toString());
|
NodeList reportsListNodes = root.getElementsByTagName(TagNames.REPORTS_LIST_ELEM.toString());
|
||||||
for (int i = 0; i < reportsListNodes.getLength(); ++i) {
|
for (int i = 0; i < reportsListNodes.getLength(); ++i) {
|
||||||
Element reportsListElem = (Element) reportsListNodes.item(i);
|
Element reportsListElem = (Element) reportsListNodes.item(i);
|
||||||
NodeList reportNodes = reportsListElem.getElementsByTagName(ExternalResultsXML.REPORT_ELEM.toString());
|
NodeList reportNodes = reportsListElem.getElementsByTagName(TagNames.REPORT_ELEM.toString());
|
||||||
for (int j = 0; j < reportNodes.getLength(); ++j) {
|
for (int j = 0; j < reportNodes.getLength(); ++j) {
|
||||||
Element reportElem = (Element) reportNodes.item(j);
|
Element reportElem = (Element) reportNodes.item(j);
|
||||||
String displayName = getChildElementContent(reportElem, ExternalResultsXML.DISPLAY_NAME_ELEM.toString());
|
String displayName = getChildElementContent(reportElem, TagNames.DISPLAY_NAME_ELEM.toString());
|
||||||
if (displayName.isEmpty()) {
|
if (displayName.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String path = getChildElementContent(reportElem, ExternalResultsXML.LOCAL_PATH_ELEM.toString());
|
String path = getChildElementContent(reportElem, TagNames.LOCAL_PATH_ELEM.toString());
|
||||||
if (displayName.isEmpty()) {
|
if (displayName.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -164,32 +224,12 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseDerivedFiles(Element rootElement) {
|
|
||||||
NodeList derivedFilesListNodes = rootElement.getElementsByTagName(ExternalResultsXML.DERIVED_FILES_LIST_ELEM.toString());
|
|
||||||
for (int i = 0; i < derivedFilesListNodes.getLength(); ++i) {
|
|
||||||
Element derivedFilesListElem = (Element) derivedFilesListNodes.item(i);
|
|
||||||
NodeList derivedFileNodes = derivedFilesListElem.getElementsByTagName(ExternalResultsXML.DERIVED_FILE_ELEM.toString());
|
|
||||||
for (int j = 0; j < derivedFileNodes.getLength(); ++j) {
|
|
||||||
Element derivedFileElem = (Element) derivedFileNodes.item(j);
|
|
||||||
String path = getChildElementContent(derivedFileElem, ExternalResultsXML.LOCAL_PATH_ELEM.toString());
|
|
||||||
if (path.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String parentPath = getChildElementContent((Element) derivedFileNodes.item(j), ExternalResultsXML.PARENT_PATH_ELEM.toString());
|
|
||||||
if (parentPath.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
externalResults.addDerivedFile(path, parentPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Element getChildElement(Element parentElement, String childElementTagName) {
|
private Element getChildElement(Element parentElement, String childElementTagName) {
|
||||||
Element childElem = null;
|
Element childElem = null;
|
||||||
NodeList childNodes = parentElement.getElementsByTagName(childElementTagName);
|
NodeList childNodes = parentElement.getElementsByTagName(childElementTagName);
|
||||||
if (childNodes.getLength() > 0) {
|
if (childNodes.getLength() > 0) {
|
||||||
if (childNodes.getLength() > 1) {
|
if (childNodes.getLength() > 1) {
|
||||||
logger.log(Level.WARNING, "Found multiple {0} child elements for {1} element in {2}, ignoring all but first occurrence", new Object[]{
|
logger.log(Level.SEVERE, "Found multiple {0} child elements for {1} element in {2}, ignoring all but first occurrence", new Object[]{
|
||||||
childElementTagName,
|
childElementTagName,
|
||||||
parentElement.getTagName(),
|
parentElement.getTagName(),
|
||||||
this.resultsFilePath}); // NON-NLS
|
this.resultsFilePath}); // NON-NLS
|
||||||
@ -201,7 +241,7 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
|
|||||||
private String getElementAttributeValue(Element element, String attributeName) {
|
private String getElementAttributeValue(Element element, String attributeName) {
|
||||||
final String attributeValue = element.getAttribute(attributeName);
|
final String attributeValue = element.getAttribute(attributeName);
|
||||||
if (attributeValue.isEmpty()) {
|
if (attributeValue.isEmpty()) {
|
||||||
logger.log(Level.WARNING, "Found {0} element missing {1} attribute in {2}", new Object[]{
|
logger.log(Level.SEVERE, "Found {0} element missing {1} attribute in {2}", new Object[]{
|
||||||
element.getTagName(),
|
element.getTagName(),
|
||||||
attributeName,
|
attributeName,
|
||||||
this.resultsFilePath});
|
this.resultsFilePath});
|
||||||
@ -214,7 +254,7 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
|
|||||||
NodeList childNodes = parentElement.getElementsByTagName(childElementTagName);
|
NodeList childNodes = parentElement.getElementsByTagName(childElementTagName);
|
||||||
if (childNodes.getLength() > 0) {
|
if (childNodes.getLength() > 0) {
|
||||||
if (childNodes.getLength() > 1) {
|
if (childNodes.getLength() > 1) {
|
||||||
logger.log(Level.WARNING, "Found multiple {0} child elements for {1} element in {2}, ignoring all but first occurrence", new Object[]{
|
logger.log(Level.SEVERE, "Found multiple {0} child elements for {1} element in {2}, ignoring all but first occurrence", new Object[]{
|
||||||
childElementTagName,
|
childElementTagName,
|
||||||
parentElement.getTagName(),
|
parentElement.getTagName(),
|
||||||
this.resultsFilePath}); // NON-NLS
|
this.resultsFilePath}); // NON-NLS
|
||||||
@ -222,17 +262,27 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
|
|||||||
Element childElement = (Element) childNodes.item(0);
|
Element childElement = (Element) childNodes.item(0);
|
||||||
content = childElement.getTextContent();
|
content = childElement.getTextContent();
|
||||||
if (content.isEmpty()) {
|
if (content.isEmpty()) {
|
||||||
logger.log(Level.WARNING, "Found {0} element with {1} child element that has no content in {2}", new Object[]{
|
logger.log(Level.SEVERE, "Found {0} element with {1} child element that has no content in {2}", new Object[]{
|
||||||
parentElement.getTagName(),
|
parentElement.getTagName(),
|
||||||
childElementTagName,
|
childElementTagName,
|
||||||
this.resultsFilePath}); // NON-NLS
|
this.resultsFilePath}); // NON-NLS
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.log(Level.WARNING, "Found {0} element missing {1} child element in {2}", new Object[]{
|
logger.log(Level.SEVERE, "Found {0} element missing {1} child element in {2}", new Object[]{
|
||||||
parentElement.getTagName(),
|
parentElement.getTagName(),
|
||||||
childElementTagName,
|
childElementTagName,
|
||||||
this.resultsFilePath}); // NON-NLS
|
this.resultsFilePath}); // NON-NLS
|
||||||
}
|
}
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void recordError(String errorMessage) {
|
||||||
|
this.logger.log(Level.SEVERE, errorMessage);
|
||||||
|
this.errors.add(new ErrorInfo(this.getClass().getSimpleName(), errorMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recordError(String errorMessage, Exception ex) {
|
||||||
|
this.logger.log(Level.SEVERE, errorMessage, ex);
|
||||||
|
this.errors.add(new ErrorInfo(this.getClass().getSimpleName(), errorMessage, ex));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user