mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 01:07: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.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.externalresults.ExternalResults;
|
||||
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.DataSourceIngestModuleProgress;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||
@ -111,7 +111,12 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM
|
||||
progressBar.progress(1);
|
||||
|
||||
// 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);
|
||||
} catch (TskCoreException | ParserConfigurationException | TransformerException | IOException ex) {
|
||||
Logger logger = IngestServices.getInstance().getLogger(moduleName);
|
||||
@ -164,18 +169,18 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM
|
||||
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
|
||||
Document doc = docBuilder.newDocument();
|
||||
Element rootElement = doc.createElement(ExternalResultsXML.ROOT_ELEM.toString());
|
||||
Element rootElement = doc.createElement(ExternalResultsXMLParser.TagNames.ROOT_ELEM.toString());
|
||||
doc.appendChild(rootElement);
|
||||
|
||||
// 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);
|
||||
|
||||
// Add an artifact element to the artifacts list element. A standard
|
||||
// artifact type is used as the required type attribute of this
|
||||
// artifact element.
|
||||
Element artifactElement = doc.createElement(ExternalResultsXML.ARTIFACT_ELEM.toString());
|
||||
artifactElement.setAttribute(ExternalResultsXML.TYPE_ATTR.toString(), ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getLabel());
|
||||
Element artifactElement = doc.createElement(ExternalResultsXMLParser.TagNames.ARTIFACT_ELEM.toString());
|
||||
artifactElement.setAttribute(ExternalResultsXMLParser.TagNames.TYPE_ATTR.toString(), ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getLabel());
|
||||
artifactsListElement.appendChild(artifactElement);
|
||||
|
||||
// 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
|
||||
// element, the data source is used as the default source file for the
|
||||
// artifact.
|
||||
Element fileElement = doc.createElement(ExternalResultsXML.SOURCE_FILE_ELEM.toString());
|
||||
Element fileElement = doc.createElement(ExternalResultsXMLParser.TagNames.SOURCE_FILE_ELEM.toString());
|
||||
artifactElement.appendChild(fileElement);
|
||||
Element pathElement = doc.createElement(ExternalResultsXML.PATH_ELEM.toString());
|
||||
Element pathElement = doc.createElement(ExternalResultsXMLParser.TagNames.PATH_ELEM.toString());
|
||||
pathElement.setTextContent(dataSourcePath);
|
||||
fileElement.appendChild(pathElement);
|
||||
|
||||
// Add an artifact attribute element to the artifact element. A standard
|
||||
// artifact attribute type is used as the required type XML attribute of
|
||||
// the artifact attribute element.
|
||||
Element artifactAttrElement = doc.createElement(ExternalResultsXML.ATTRIBUTE_ELEM.toString());
|
||||
artifactAttrElement.setAttribute(ExternalResultsXML.TYPE_ATTR.toString(), ATTRIBUTE_TYPE.TSK_SET_NAME.getLabel());
|
||||
Element artifactAttrElement = doc.createElement(ExternalResultsXMLParser.TagNames.ATTRIBUTE_ELEM.toString());
|
||||
artifactAttrElement.setAttribute(ExternalResultsXMLParser.TagNames.TYPE_ATTR.toString(), ATTRIBUTE_TYPE.TSK_SET_NAME.getLabel());
|
||||
artifactElement.appendChild(artifactAttrElement);
|
||||
|
||||
// Add the required value element to the artifact attribute element,
|
||||
// with an optional type XML attribute of ExternalXML.VALUE_TYPE_TEXT,
|
||||
// which is the default.
|
||||
Element artifactAttributeValueElement = doc.createElement(ExternalResultsXML.VALUE_ELEM.toString());
|
||||
Element artifactAttributeValueElement = doc.createElement(ExternalResultsXMLParser.TagNames.VALUE_ELEM.toString());
|
||||
artifactAttributeValueElement.setTextContent("SampleInterestingFilesSet");
|
||||
artifactAttrElement.appendChild(artifactAttributeValueElement);
|
||||
|
||||
// Add an optional source module element to the artifct attribute
|
||||
// element.
|
||||
Element artifactAttrSourceElement = doc.createElement(ExternalResultsXML.SOURCE_MODULE_ELEM.toString());
|
||||
Element artifactAttrSourceElement = doc.createElement(ExternalResultsXMLParser.TagNames.SOURCE_MODULE_ELEM.toString());
|
||||
artifactAttrSourceElement.setTextContent(moduleName);
|
||||
artifactAttrElement.appendChild(artifactAttrSourceElement);
|
||||
|
||||
// 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
|
||||
// default for the source file.
|
||||
artifactElement = doc.createElement(ExternalResultsXML.ARTIFACT_ELEM.toString());
|
||||
artifactElement.setAttribute(ExternalResultsXML.TYPE_ATTR.toString(), "SampleArtifactType");
|
||||
artifactElement = doc.createElement(ExternalResultsXMLParser.TagNames.ARTIFACT_ELEM.toString());
|
||||
artifactElement.setAttribute(ExternalResultsXMLParser.TagNames.TYPE_ATTR.toString(), "SampleArtifactType");
|
||||
artifactsListElement.appendChild(artifactElement);
|
||||
|
||||
// Add artifact attribute elements with user-defined types to the
|
||||
// artifact element, adding value elements of assorted types.
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
artifactAttrElement = doc.createElement(ExternalResultsXML.ATTRIBUTE_ELEM.toString());
|
||||
artifactAttrElement.setAttribute(ExternalResultsXML.TYPE_ATTR.toString(), "SampleArtifactAttributeType");
|
||||
artifactAttrElement = doc.createElement(ExternalResultsXMLParser.TagNames.ATTRIBUTE_ELEM.toString());
|
||||
artifactAttrElement.setAttribute(ExternalResultsXMLParser.TagNames.TYPE_ATTR.toString(), "SampleArtifactAttributeType");
|
||||
artifactElement.appendChild(artifactAttrElement);
|
||||
artifactAttributeValueElement = doc.createElement(ExternalResultsXML.VALUE_ELEM.toString());
|
||||
artifactAttributeValueElement = doc.createElement(ExternalResultsXMLParser.TagNames.VALUE_ELEM.toString());
|
||||
switch (i) {
|
||||
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");
|
||||
break;
|
||||
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");
|
||||
break;
|
||||
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");
|
||||
break;
|
||||
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");
|
||||
break;
|
||||
}
|
||||
@ -245,25 +250,25 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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");
|
||||
reportElement.appendChild(reportDisplayNameElement);
|
||||
|
||||
// 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);
|
||||
reportElement.appendChild(reportPathElement);
|
||||
|
||||
// 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);
|
||||
|
||||
// Add derived file elements to the derived files list element. Each
|
||||
@ -273,13 +278,13 @@ public class SampleExecutableDataSourceIngestModule implements DataSourceIngestM
|
||||
// parent.
|
||||
Element parentPathElement = null;
|
||||
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);
|
||||
Element localPathElement = doc.createElement(ExternalResultsXML.LOCAL_PATH_ELEM.toString());
|
||||
Element localPathElement = doc.createElement(ExternalResultsXMLParser.TagNames.LOCAL_PATH_ELEM.toString());
|
||||
localPathElement.setTextContent(filePath);
|
||||
derivedFileElement.appendChild(localPathElement);
|
||||
if (parentPathElement == null) {
|
||||
parentPathElement = doc.createElement(ExternalResultsXML.PARENT_PATH_ELEM.toString());
|
||||
parentPathElement = doc.createElement(ExternalResultsXMLParser.TagNames.PARENT_PATH_ELEM.toString());
|
||||
parentPathElement.setTextContent(dataSourcePath);
|
||||
derivedFileElement.appendChild(parentPathElement);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ final public class ExternalResults {
|
||||
private final List<Artifact> artifacts = new ArrayList<>();
|
||||
private final List<Report> reports = new ArrayList<>();
|
||||
private final List<DerivedFile> derivedFiles = new ArrayList<>();
|
||||
|
||||
|
||||
ExternalResults(Content dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
@ -23,10 +23,12 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
||||
import org.sleuthkit.autopsy.coreutils.ErrorInfo;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
|
||||
@ -36,232 +38,165 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.DerivedFile;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Mechanism to import blackboard items, derived files, etc. It is decoupled
|
||||
* from the actual parsing/interfacing with external data.
|
||||
* Uses a standard representation of results data (e.g., artifacts, derived
|
||||
* 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 String EVENT_STRING = "External Results";
|
||||
private final List<ErrorInfo> errors = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Import results for a data source from an XML localFile (see
|
||||
* org.sleuthkit.autopsy.externalresults.autopsy_external_results.xsd).
|
||||
* Import results generated by a process external to Autopsy into Autopsy.
|
||||
*
|
||||
* @param dataSource A data source.
|
||||
* @param resultsXmlPath Path to an XML localFile containing results (e.g.,
|
||||
* blackboard artifacts, derived files, reports) from the data source.
|
||||
* @param results A standard representation of results data (e.g.,
|
||||
* 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
|
||||
ExternalResults results = new ExternalResultsXMLParser(dataSource, resultsXmlPath).parse(); // RJCTODO: Return error messages
|
||||
// RJCTODO: Get external results, restore ExternalResults parser interface
|
||||
importDerivedFiles(results); // Import files first, they may be artifact sources.
|
||||
importArtifacts(dataSource, results);
|
||||
public List<ErrorInfo> importResults(ExternalResults results) {
|
||||
// Import files first, they may be artifactData sources.
|
||||
importDerivedFiles(results);
|
||||
importArtifacts(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();
|
||||
for (ExternalResults.DerivedFile fileData : results.getDerivedFiles()) {
|
||||
String filePath = Case.getCurrentCase().getCaseDirectory() + File.separator + fileData.getLocalPath();
|
||||
try {
|
||||
String localPath = fileData.getLocalPath();
|
||||
File localFile = new File(localPath); // RJCTODO: State/check ExternalResults contract that is not empty
|
||||
File localFile = new File(filePath);
|
||||
if (!localFile.exists()) {
|
||||
AbstractFile parentFile = findFileInDatabase(fileData.getParentPath());
|
||||
if (parentFile == null) {
|
||||
String relativePath = getPathRelativeToCaseFolder(fileData.getLocalPath());
|
||||
DerivedFile derivedFile = fileManager.addDerivedFile(localFile.getName(), relativePath, localFile.length(),
|
||||
0, 0, 0, 0, // Do not currently have localFile times for derived files, should they provide via XML?
|
||||
true, parentFile, "", "", "", "");
|
||||
|
||||
if (derivedFile != null) {
|
||||
IngestServices.getInstance().fireModuleContentEvent(new ModuleContentEvent(derivedFile));
|
||||
}
|
||||
AbstractFile parentFile = findFile(results.getDataSource(), fileData.getParentPath());
|
||||
if (parentFile != null) {
|
||||
DerivedFile derivedFile = fileManager.addDerivedFile(localFile.getName(), fileData.getLocalPath(), localFile.length(),
|
||||
0, 0, 0, 0, // Do not currently have file times for derived files from external processes.
|
||||
true, parentFile,
|
||||
"", "", "", ""); // Not currently providing derivation info for derived files from external processes.
|
||||
IngestServices.getInstance().fireModuleContentEvent(new ModuleContentEvent(derivedFile));
|
||||
} else {
|
||||
// RJCTODO: parent file not in database
|
||||
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 {
|
||||
// RJCTODO: file missing
|
||||
String errorMessage = String.format("Could not import derived file at %s, file does not exist", filePath);
|
||||
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage);
|
||||
this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage));
|
||||
}
|
||||
} 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and add new blackboard artifacts, attributes, and types
|
||||
*
|
||||
* @param results
|
||||
* @param dataSource
|
||||
*/
|
||||
private static void importArtifacts(Content dataSource, ExternalResults results) {
|
||||
for (ExternalResults.Artifact art : results.getArtifacts()) {
|
||||
private void importArtifacts(ExternalResults results) {
|
||||
SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase();
|
||||
for (ExternalResults.Artifact artifactData : results.getArtifacts()) {
|
||||
try {
|
||||
// Get the artifact type id if defined, or create a new
|
||||
// user-defined artifact type.
|
||||
int artifactTypeId;
|
||||
BlackboardArtifact.ARTIFACT_TYPE stdArtType = isStandardArtifactType(art.getType());
|
||||
if (stdArtType != null) {
|
||||
artifactTypeId = stdArtType.getTypeID();
|
||||
} else {
|
||||
artifactTypeId = Case.getCurrentCase().getSleuthkitCase().addArtifactType(art.getType(), art.getType());
|
||||
// Add the artifact to the case database.
|
||||
boolean artifactTypeIsUserDefined = false;
|
||||
int artifactTypeId = caseDb.getArtifactTypeIdIfExists(artifactData.getType());
|
||||
if (artifactTypeId == -1) {
|
||||
artifactTypeId = caseDb.addArtifactType(artifactData.getType(), artifactData.getType());
|
||||
artifactTypeIsUserDefined = true;
|
||||
}
|
||||
Content sourceFile = findFile(results.getDataSource(), artifactData.getSourceFilePath());
|
||||
BlackboardArtifact artifact = sourceFile.newArtifact(artifactTypeId);
|
||||
|
||||
Collection<BlackboardAttribute> bbAttributes = new ArrayList<>();
|
||||
for (ExternalResults.ArtifactAttribute attr : art.getAttributes()) {
|
||||
int bbAttrTypeId;
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE stdAttrType = isStandardAttributeType(attr.getType());
|
||||
if (stdAttrType != null) {
|
||||
bbAttrTypeId = stdAttrType.getTypeID();
|
||||
} else {
|
||||
// assume it's user defined RJCTODO fix
|
||||
bbAttrTypeId = Case.getCurrentCase().getSleuthkitCase().addAttrType(attr.getType(), attr.getType());
|
||||
// Add the artifact's attributes to the case database.
|
||||
Collection<BlackboardAttribute> attributes = new ArrayList<>();
|
||||
for (ExternalResults.ArtifactAttribute attributeData : artifactData.getAttributes()) {
|
||||
int attributeTypeId = caseDb.getAttrTypeIdIfExists(attributeData.getType());
|
||||
if (artifactTypeId == -1) {
|
||||
artifactTypeId = caseDb.addArtifactType(attributeData.getType(), attributeData.getType());
|
||||
}
|
||||
|
||||
BlackboardAttribute bbAttr = null;
|
||||
switch (attr.getValueType()) {
|
||||
switch (attributeData.getValueType()) {
|
||||
case "text": //NON-NLS
|
||||
bbAttr = new BlackboardAttribute(bbAttrTypeId, attr.getSourceModule(), attr.getValue());
|
||||
attributes.add(new BlackboardAttribute(attributeTypeId, attributeData.getSourceModule(), attributeData.getValue()));
|
||||
break;
|
||||
case "int32": //NON-NLS
|
||||
int intValue = Integer.parseInt(attr.getValue());
|
||||
bbAttr = new BlackboardAttribute(bbAttrTypeId, attr.getSourceModule(), intValue);
|
||||
int intValue = Integer.parseInt(attributeData.getValue());
|
||||
attributes.add(new BlackboardAttribute(attributeTypeId, attributeData.getSourceModule(), intValue));
|
||||
break;
|
||||
case "int64": //NON-NLS
|
||||
long longValue = Long.parseLong(attr.getValue());
|
||||
bbAttr = new BlackboardAttribute(bbAttrTypeId, attr.getSourceModule(), longValue);
|
||||
long longValue = Long.parseLong(attributeData.getValue());
|
||||
attributes.add(new BlackboardAttribute(attributeTypeId, attributeData.getSourceModule(), longValue));
|
||||
break;
|
||||
case "double": //NON-NLS
|
||||
double doubleValue = Double.parseDouble(attr.getValue());
|
||||
bbAttr = new BlackboardAttribute(bbAttrTypeId, attr.getSourceModule(), doubleValue);
|
||||
double doubleValue = Double.parseDouble(attributeData.getValue());
|
||||
attributes.add(new BlackboardAttribute(attributeTypeId, attributeData.getSourceModule(), doubleValue));
|
||||
break;
|
||||
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;
|
||||
}
|
||||
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
|
||||
Content currContent = null;
|
||||
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
|
||||
if (!artifactTypeIsUserDefined) {
|
||||
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(this.getClass().getSimpleName(), BlackboardArtifact.ARTIFACT_TYPE.fromID(artifactTypeId)));
|
||||
}
|
||||
} 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()) {
|
||||
String reportPath = Case.getCurrentCase().getCaseDirectory() + File.separator + report.getLocalPath();
|
||||
try {
|
||||
String reportPath = report.getLocalPath();
|
||||
File reportFile = new File(reportPath);
|
||||
if (reportFile.exists()) {
|
||||
// Try to get a relative local path
|
||||
String relPath = reportPath;
|
||||
Path pathTo = Paths.get(reportPath);
|
||||
if (pathTo.isAbsolute()) {
|
||||
Path pathBase = Paths.get(Case.getCurrentCase().getCaseDirectory());
|
||||
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());
|
||||
}
|
||||
Case.getCurrentCase().getSleuthkitCase().addReport(reportPath, report.getDisplayName());
|
||||
} else {
|
||||
String errorMessage = String.format("Could not import report at %s, file does not exist", reportPath);
|
||||
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage);
|
||||
this.errors.add(new ErrorInfo(ExternalResultsImporter.class.getName(), errorMessage));
|
||||
}
|
||||
} 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* util function
|
||||
*
|
||||
* @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);
|
||||
private AbstractFile findFile(Content dataSource, String filePath) throws TskCoreException {
|
||||
AbstractFile file = null;
|
||||
Path path = Paths.get(filePath);
|
||||
if (path.isAbsolute()) {
|
||||
Path pathBase = Paths.get(Case.getCurrentCase().getCaseDirectory());
|
||||
try {
|
||||
Path pathRelative = pathBase.relativize(path);
|
||||
relativePath = pathRelative.toString();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// RJCTODO: Fix this
|
||||
logger.log(Level.WARNING, "Report file {0} path may be incorrect. The report record will still be added to the database.", localPath);
|
||||
FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
|
||||
List<AbstractFile> files = fileManager.openFiles(dataSource, filePath);
|
||||
if (files.size() > 0) {
|
||||
file = files.get(0);
|
||||
if (files.size() > 1) {
|
||||
String errorMessage = String.format("Ambiguous file path: %s", filePath);
|
||||
ExternalResultsImporter.logger.log(Level.SEVERE, errorMessage);
|
||||
this.errors.add(new ErrorInfo(this.getClass().getName(), errorMessage));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// RJCTODO: Path is not absolute
|
||||
// RJCTODO: Need a look up that goes for relative path
|
||||
}
|
||||
return relativePath;
|
||||
}
|
||||
|
||||
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;
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
@ -19,11 +19,12 @@
|
||||
package org.sleuthkit.autopsy.externalresults;
|
||||
|
||||
import java.util.List;
|
||||
import org.sleuthkit.autopsy.coreutils.ErrorInfo;
|
||||
|
||||
/**
|
||||
* Interface for parsers that convert some representation of results data (
|
||||
* e.g., artifacts, derived files, reports) generated by a process external to
|
||||
* Autopsy into a form ready for import into Autopsy.
|
||||
* Interface for parsers that convert some representation of results data (e.g.,
|
||||
* artifacts, derived files, reports) generated by a process external to Autopsy
|
||||
* into a form ready for import into Autopsy.
|
||||
*/
|
||||
public interface ExternalResultsParser {
|
||||
|
||||
@ -32,15 +33,17 @@ public interface ExternalResultsParser {
|
||||
* external to Autopsy and supplied to the parser via its constructor into a
|
||||
* 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
|
||||
|
||||
/**
|
||||
* Gets error messages describing any errors encountered while parsing the
|
||||
* input results representation.
|
||||
* Gets error information describing any errors encountered while parsing
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.ErrorInfo;
|
||||
import org.sleuthkit.autopsy.coreutils.XMLUtil;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.w3c.dom.Document;
|
||||
@ -28,8 +31,8 @@ import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Parses an XML representation of externally generated results (artifacts,
|
||||
* derived files, and reports).
|
||||
* Parses an XML representation of of results data (e.g., artifacts, derived
|
||||
* files, reports) generated by a process external to Autopsy into Autopsy.
|
||||
*/
|
||||
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 final String resultsFilePath;
|
||||
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.
|
||||
*
|
||||
* @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;
|
||||
externalResults = new ExternalResults(dataSource);
|
||||
}
|
||||
@ -59,42 +101,60 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
|
||||
final Document doc = XMLUtil.loadDoc(ExternalResultsXMLParser.class, this.resultsFilePath, XSD_FILE);
|
||||
if (doc != null) {
|
||||
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);
|
||||
parseReports(rootElem);
|
||||
parseDerivedFiles(rootElem);
|
||||
} else {
|
||||
logger.log(Level.SEVERE, "Did not find {0} root element of {2}", new Object[]{
|
||||
ExternalResultsXML.ROOT_ELEM.toString(), this.resultsFilePath}); //NON-NLS
|
||||
String errorMessage = String.format("Did not find %s root element of %s", TagNames.ROOT_ELEM.toString(), this.resultsFilePath);
|
||||
recordError(errorMessage);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Error parsing " + this.resultsFilePath, e); //NON-NLS
|
||||
} catch (Exception ex) {
|
||||
String errorMessage = String.format("Error parsing %s", this.resultsFilePath);
|
||||
recordError(errorMessage, ex);
|
||||
}
|
||||
return externalResults;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getErrorMessages() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
public List<ErrorInfo> getErrorInfo() {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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()) {
|
||||
Element sourceFileElem = getChildElement(artifactElem, ExternalResultsXML.SOURCE_FILE_ELEM.toString());
|
||||
if (sourceFileElem != null) {
|
||||
final String sourceFilePath = this.getChildElementContent((Element) sourceFileElem, ExternalResultsXML.PATH_ELEM.toString());
|
||||
if (!sourceFilePath.isEmpty()) {
|
||||
ExternalResults.Artifact artifact = externalResults.addArtifact(type, sourceFilePath);
|
||||
parseArtifactAttributes(artifactElem, artifact);
|
||||
}
|
||||
final String sourceFilePath = this.getChildElementContent((Element) artifactElem, TagNames.PATH_ELEM.toString());
|
||||
if (!sourceFilePath.isEmpty()) {
|
||||
ExternalResults.Artifact artifact = externalResults.addArtifact(type, sourceFilePath);
|
||||
parseArtifactAttributes(artifactElem, artifact);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -102,60 +162,60 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
|
||||
}
|
||||
|
||||
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) {
|
||||
// Get the type of the artifact attribute.
|
||||
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()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// 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) {
|
||||
continue;
|
||||
}
|
||||
final String value = valueElem.getTextContent();
|
||||
if (value.isEmpty()) {
|
||||
logger.log(Level.WARNING, "Found {0} element that has no content in {1}", new Object[]{
|
||||
ExternalResultsXML.VALUE_ELEM.toString(), this.resultsFilePath});
|
||||
String errorMessage = String.format("Found %s element that has no content in %s",
|
||||
TagNames.VALUE_ELEM.toString(), this.resultsFilePath);
|
||||
recordError(errorMessage);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Get the value type.
|
||||
String valueType = valueElem.getAttribute(ExternalResultsXML.TYPE_ATTR.toString());
|
||||
String valueType = valueElem.getAttribute(TagNames.TYPE_ATTR.toString());
|
||||
if (valueType.isEmpty()) {
|
||||
valueType = ExternalResultsXML.VALUE_TYPE_TEXT.toString();
|
||||
}
|
||||
valueType = TagNames.VALUE_TYPE_TEXT.toString();
|
||||
}
|
||||
// Get the source module for the artifact attribute.
|
||||
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() > 1) {
|
||||
logger.log(Level.WARNING, "Found multiple {0} child elements for {1} element in {2}, ignoring all but first occurrence", new Object[]{
|
||||
ExternalResultsXML.SOURCE_MODULE_ELEM.toString(),
|
||||
attributeElem.getTagName(),
|
||||
this.resultsFilePath}); // NON-NLS
|
||||
String errorMessage = String.format("Found multiple %s child elements for %s element in %s, ignoring all but first occurrence",
|
||||
TagNames.SOURCE_MODULE_ELEM.toString(), attributeElem.getTagName(), this.resultsFilePath);
|
||||
recordError(errorMessage);
|
||||
}
|
||||
Element srcModuleElem = (Element) sourceModuleNodes.item(0);
|
||||
sourceModule = srcModuleElem.getTextContent();
|
||||
}
|
||||
}
|
||||
// Add the attribute to the artifact.
|
||||
artifact.addAttribute(type, value, valueType, sourceModule);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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()) {
|
||||
continue;
|
||||
}
|
||||
String path = getChildElementContent(reportElem, ExternalResultsXML.LOCAL_PATH_ELEM.toString());
|
||||
String path = getChildElementContent(reportElem, TagNames.LOCAL_PATH_ELEM.toString());
|
||||
if (displayName.isEmpty()) {
|
||||
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) {
|
||||
Element childElem = null;
|
||||
NodeList childNodes = parentElement.getElementsByTagName(childElementTagName);
|
||||
if (childNodes.getLength() > 0) {
|
||||
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,
|
||||
parentElement.getTagName(),
|
||||
this.resultsFilePath}); // NON-NLS
|
||||
@ -201,7 +241,7 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
|
||||
private String getElementAttributeValue(Element element, String attributeName) {
|
||||
final String attributeValue = element.getAttribute(attributeName);
|
||||
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(),
|
||||
attributeName,
|
||||
this.resultsFilePath});
|
||||
@ -214,7 +254,7 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
|
||||
NodeList childNodes = parentElement.getElementsByTagName(childElementTagName);
|
||||
if (childNodes.getLength() > 0) {
|
||||
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,
|
||||
parentElement.getTagName(),
|
||||
this.resultsFilePath}); // NON-NLS
|
||||
@ -222,17 +262,27 @@ public final class ExternalResultsXMLParser implements ExternalResultsParser {
|
||||
Element childElement = (Element) childNodes.item(0);
|
||||
content = childElement.getTextContent();
|
||||
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(),
|
||||
childElementTagName,
|
||||
this.resultsFilePath}); // NON-NLS
|
||||
}
|
||||
} 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(),
|
||||
childElementTagName,
|
||||
this.resultsFilePath}); // NON-NLS
|
||||
}
|
||||
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