Continue to work on user-defined file types

This commit is contained in:
Richard Cordovano 2014-12-18 16:59:34 -05:00
parent 8d3135c02b
commit dcd632e5e6
5 changed files with 304 additions and 261 deletions

View File

@ -56,17 +56,100 @@ import org.xml.sax.SAXException;
public class XMLUtil { public class XMLUtil {
/** /**
* Creates a W3C DOM document. * Creates a W3C DOM.
* *
* @return The document object. * @return The document object.
* @throws ParserConfigurationException * @throws ParserConfigurationException
*/ */
public static Document createDoc() throws ParserConfigurationException { public static Document createDocument() throws ParserConfigurationException {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder(); DocumentBuilder builder = builderFactory.newDocumentBuilder();
return builder.newDocument(); return builder.newDocument();
} }
/**
* Loads an XML document into a WC3 DOM and validates it using a schema
* packaged as a class resource.
*
* @param <T> The name of the class associated with the resource.
* @param docPath The full path to the XML document.
* @param clazz The class associated with the schema resource.
* @param schemaResourceName The name of the schema resource.
* @return The WC3 DOM document object.
* @throws IOException
* @throws ParserConfigurationException
* @throws SAXException
*/
public static <T> Document loadDocument(String docPath, Class<T> clazz, String schemaResourceName) throws IOException, ParserConfigurationException, SAXException {
Document doc = loadDocument(docPath);
validateDocument(doc, clazz, schemaResourceName);
return doc;
}
/**
* Loads an XML document into a WC3 DOM.
*
* @param docPath The full path to the XML document.
* @return The WC3 DOM document object.
* @throws ParserConfigurationException
* @throws SAXException
* @throws IOException
*/
public static Document loadDocument(String docPath) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document doc = builder.parse(new FileInputStream(docPath));
return doc;
}
/**
* Validates a WC3 DOM using a schema packaged as a class resource.
*
* @param doc
* @param clazz
* @param schemaResourceName
* @throws SAXException
* @throws IOException
*/
public static <T> void validateDocument(final Document doc, Class<T> clazz, String schemaResourceName) throws SAXException, IOException {
PlatformUtil.extractResourceToUserConfigDir(clazz, schemaResourceName, false);
File schemaFile = new File(Paths.get(PlatformUtil.getUserConfigDirectory(), schemaResourceName).toAbsolutePath().toString());
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(schemaFile);
Validator validator = schema.newValidator();
validator.validate(new DOMSource(doc), new DOMResult());
}
/**
* Saves a WC3 DOM by writing it to an XML document.
*
* @param doc The WC3 DOM document object.
* @param docPath The full path to the XML document.
* @param encoding Encoding scheme to use for the XML document, e.g.,
* "UTF-8."
* @throws TransformerConfigurationException
* @throws FileNotFoundException
* @throws UnsupportedEncodingException
* @throws TransformerException
* @throws IOException
*/
public static void saveDocument(final Document doc, String encoding, String docPath) throws TransformerConfigurationException, FileNotFoundException, UnsupportedEncodingException, TransformerException, IOException {
TransformerFactory xf = TransformerFactory.newInstance();
xf.setAttribute("indent-number", 1); //NON-NLS
Transformer xformer = xf.newTransformer();
xformer.setOutputProperty(OutputKeys.METHOD, "xml"); //NON-NLS
xformer.setOutputProperty(OutputKeys.INDENT, "yes"); //NON-NLS
xformer.setOutputProperty(OutputKeys.ENCODING, encoding);
xformer.setOutputProperty(OutputKeys.STANDALONE, "yes"); //NON-NLS
xformer.setOutputProperty(OutputKeys.VERSION, "1.0");
File file = new File(docPath);
try (FileOutputStream stream = new FileOutputStream(file)) {
Result out = new StreamResult(new OutputStreamWriter(stream, encoding));
xformer.transform(new DOMSource(doc), out);
stream.flush();
}
}
/** /**
* Utility to validate XML files against pre-defined schema files. * Utility to validate XML files against pre-defined schema files.
* *
@ -84,6 +167,7 @@ public class XMLUtil {
* IngestModuleLoader. * IngestModuleLoader.
* *
*/ */
// RJCTODO: Deprecate.
public static <T> boolean xmlIsValid(DOMSource xmlfile, Class<T> clazz, String schemaFile) { public static <T> boolean xmlIsValid(DOMSource xmlfile, Class<T> clazz, String schemaFile) {
try { try {
PlatformUtil.extractResourceToUserConfigDir(clazz, schemaFile, false); PlatformUtil.extractResourceToUserConfigDir(clazz, schemaFile, false);
@ -121,6 +205,7 @@ public class XMLUtil {
* IngestModuleLoader. * IngestModuleLoader.
* *
*/ */
// RJCTODO: Deprecate.
public static <T> boolean xmlIsValid(Document doc, Class<T> clazz, String type) { public static <T> boolean xmlIsValid(Document doc, Class<T> clazz, String type) {
DOMSource dms = new DOMSource(doc); DOMSource dms = new DOMSource(doc);
return xmlIsValid(dms, clazz, type); return xmlIsValid(dms, clazz, type);
@ -132,6 +217,7 @@ public class XMLUtil {
* @param clazz the class this method is invoked from * @param clazz the class this method is invoked from
* @param xmlPath the full path to the file to load * @param xmlPath the full path to the file to load
*/ */
// RJCTODO: Deprecate.
public static <T> Document loadDoc(Class<T> clazz, String xmlPath) { public static <T> Document loadDoc(Class<T> clazz, String xmlPath) {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
Document ret = null; Document ret = null;
@ -165,39 +251,6 @@ public class XMLUtil {
return ret; return ret;
} }
/**
* Loads an XML document into a WC3 DOM and validates it against a schema
* packaged as a class resource.
*
* @param <T> The name of the class associated with the resource.
* @param clazz The class associated with the resource.
* @param docPath The full path to the XML document.
* @param schemaResourceName The name of the schema resource
* @return A WC3 DOM representation of the document
* @throws IOException
* @throws org.sleuthkit.autopsy.coreutils.XMLUtil.XmlUtilException
*/
public static <T> Document loadAndValidateDoc(Class<T> clazz, String docPath, String schemaResourceName) throws IOException, ParserConfigurationException, SAXException {
/**
* Parse the XML file into a DOM.
*/
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document doc = builder.parse(new FileInputStream(docPath));
/**
* Extract the schema and validate the DOM.
*/
PlatformUtil.extractResourceToUserConfigDir(clazz, schemaResourceName, false);
File schemaFile = new File(Paths.get(PlatformUtil.getUserConfigDirectory(), schemaResourceName).toAbsolutePath().toString());
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(schemaFile);
Validator validator = schema.newValidator();
validator.validate(new DOMSource(doc), new DOMResult());
return doc;
}
/** /**
* Saves XML files to disk * Saves XML files to disk
* *
@ -206,6 +259,7 @@ public class XMLUtil {
* @param encoding to encoding, such as "UTF-8", to encode the file with * @param encoding to encoding, such as "UTF-8", to encode the file with
* @param doc the document to save * @param doc the document to save
*/ */
// RJCTODO: Deprecate.
public static <T> boolean saveDoc(Class<T> clazz, String xmlPath, String encoding, final Document doc) { public static <T> boolean saveDoc(Class<T> clazz, String xmlPath, String encoding, final Document doc) {
TransformerFactory xf = TransformerFactory.newInstance(); TransformerFactory xf = TransformerFactory.newInstance();
xf.setAttribute("indent-number", 1); //NON-NLS xf.setAttribute("indent-number", 1); //NON-NLS

View File

@ -90,8 +90,9 @@ final class FileType {
} }
/** /**
* Gets the interesting files set name assigned to this file type * Gets the interesting files set name assigned to this file type.
* @return *
* @return The files set name, possibly empty.
*/ */
String getFilesSetName() { String getFilesSetName() {
return this.filesSetName; return this.filesSetName;

View File

@ -44,19 +44,10 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
private static final String RAW_SIGNATURE_TYPE_COMBO_BOX_ITEM = NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.signatureComboBox.rawItem"); private static final String RAW_SIGNATURE_TYPE_COMBO_BOX_ITEM = NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.signatureComboBox.rawItem");
private static final String ASCII_SIGNATURE_TYPE_COMBO_BOX_ITEM = NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.signatureComboBox.asciiItem"); private static final String ASCII_SIGNATURE_TYPE_COMBO_BOX_ITEM = NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.signatureComboBox.asciiItem");
/**
* These two fields are used to synthesize default names for user-defined
* types. This is a thread-safe implementation. All interactions with
* instances of this panel should occur on the EDT, so this is defensive
* programming.
*/
private static final String DEFAULT_TYPE_NAME_BASE = "userdefined/userdefined"; //NON-NLS
private static final AtomicInteger defaultTypeNameCounter = new AtomicInteger(1); // RJCTODO: Need to save and init counter
/** /**
* The list model for the file types list component of this panel is the set * The list model for the file types list component of this panel is the set
* of type names of the user-defined file types. A mapping of the file type * of type names of the user-defined file types. A mapping of the file type
* names to file type objects completes the model. * names to file type objects lies behind the list model.
*/ */
private DefaultListModel<String> typesListModel; private DefaultListModel<String> typesListModel;
private Map<String, FileType> fileTypes; private Map<String, FileType> fileTypes;
@ -70,19 +61,13 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
} }
/** /**
* Does child component initialization in addition to the the Matisse * Does child component initialization in addition to that done by the
* generated initialization. * Matisse generated code.
*/ */
private void customizeComponents() { private void customizeComponents() {
/**
* Make a model for the file types list component.
*/
this.typesListModel = new DefaultListModel<>(); this.typesListModel = new DefaultListModel<>();
this.typesList.setModel(this.typesListModel); this.typesList.setModel(this.typesListModel);
/**
* Make a model for the signature type combo box component.
*/
DefaultComboBoxModel<String> sigTypeComboBoxModel = new DefaultComboBoxModel<>(); DefaultComboBoxModel<String> sigTypeComboBoxModel = new DefaultComboBoxModel<>();
sigTypeComboBoxModel.addElement(FileTypeIdGlobalSettingsPanel.RAW_SIGNATURE_TYPE_COMBO_BOX_ITEM); sigTypeComboBoxModel.addElement(FileTypeIdGlobalSettingsPanel.RAW_SIGNATURE_TYPE_COMBO_BOX_ITEM);
sigTypeComboBoxModel.addElement(FileTypeIdGlobalSettingsPanel.ASCII_SIGNATURE_TYPE_COMBO_BOX_ITEM); sigTypeComboBoxModel.addElement(FileTypeIdGlobalSettingsPanel.ASCII_SIGNATURE_TYPE_COMBO_BOX_ITEM);
@ -100,35 +85,20 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
} }
/** /**
* Populates the child components with file types obtained from the * @inheritDoc
* user-defined file types manager.
*/ */
@Override @Override
public void load() { public void load() {
/**
* Get the user-defined file types and set up a list model for the file
* types list component.
*/
this.fileTypes = UserDefinedFileTypesManager.getInstance().getUserDefinedFileTypes(); this.fileTypes = UserDefinedFileTypesManager.getInstance().getUserDefinedFileTypes();
this.setFileTypesListModel(); this.setFileTypesListModel();
/**
* Add a selection listener to populate the file type details
* display/edit components.
*/
this.typesList.addListSelectionListener(new TypesListSelectionListener()); this.typesList.addListSelectionListener(new TypesListSelectionListener());
/**
* If there is at least one user-defined file type, select it the file
* types list component.
*/
if (!this.typesListModel.isEmpty()) { if (!this.typesListModel.isEmpty()) {
this.typesList.setSelectedIndex(0); this.typesList.setSelectedIndex(0);
} }
} }
/** /**
* Stores any changes to the user-defined types. * @inheritDoc
*/ */
@Override @Override
public void store() { public void store() {
@ -158,6 +128,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
FileTypeIdGlobalSettingsPanel.this.signatureTypeComboBox.setSelectedItem(sigType == FileType.Signature.Type.RAW ? FileTypeIdGlobalSettingsPanel.RAW_SIGNATURE_TYPE_COMBO_BOX_ITEM : FileTypeIdGlobalSettingsPanel.ASCII_SIGNATURE_TYPE_COMBO_BOX_ITEM); FileTypeIdGlobalSettingsPanel.this.signatureTypeComboBox.setSelectedItem(sigType == FileType.Signature.Type.RAW ? FileTypeIdGlobalSettingsPanel.RAW_SIGNATURE_TYPE_COMBO_BOX_ITEM : FileTypeIdGlobalSettingsPanel.ASCII_SIGNATURE_TYPE_COMBO_BOX_ITEM);
FileTypeIdGlobalSettingsPanel.this.offsetTextField.setText(Long.toString(signature.getOffset())); FileTypeIdGlobalSettingsPanel.this.offsetTextField.setText(Long.toString(signature.getOffset()));
FileTypeIdGlobalSettingsPanel.this.postHitCheckBox.setSelected(fileType.alertOnMatch()); FileTypeIdGlobalSettingsPanel.this.postHitCheckBox.setSelected(fileType.alertOnMatch());
FileTypeIdGlobalSettingsPanel.this.filesSetNameTextField.setText(fileType.getFilesSetName());
FileTypeIdGlobalSettingsPanel.this.deleteTypeButton.setEnabled(true); FileTypeIdGlobalSettingsPanel.this.deleteTypeButton.setEnabled(true);
} }
} }
@ -187,6 +158,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
this.signatureTextField.setText(""); //NON-NLS this.signatureTextField.setText(""); //NON-NLS
this.offsetTextField.setText(""); //NON-NLS this.offsetTextField.setText(""); //NON-NLS
this.postHitCheckBox.setSelected(false); this.postHitCheckBox.setSelected(false);
this.filesSetNameTextField.setText("");
} }
/** /**
@ -372,7 +344,6 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
private void newTypeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTypeButtonActionPerformed private void newTypeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTypeButtonActionPerformed
this.clearTypeDetailsComponents(); this.clearTypeDetailsComponents();
this.mimeTypeTextField.setText(FileTypeIdGlobalSettingsPanel.DEFAULT_TYPE_NAME_BASE + FileTypeIdGlobalSettingsPanel.defaultTypeNameCounter.getAndIncrement());
}//GEN-LAST:event_newTypeButtonActionPerformed }//GEN-LAST:event_newTypeButtonActionPerformed
private void deleteTypeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteTypeButtonActionPerformed private void deleteTypeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteTypeButtonActionPerformed
@ -429,16 +400,16 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
*/ */
String filesSetName = this.filesSetNameTextField.getText(); String filesSetName = this.filesSetNameTextField.getText();
if (this.postHitCheckBox.isSelected() && filesSetName.isEmpty()) { if (this.postHitCheckBox.isSelected() && filesSetName.isEmpty()) {
JOptionPane.showMessageDialog(null, JOptionPane.showMessageDialog(null,
NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.message"), NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.message"),
NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.title"), NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.invalidOffset.title"),
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
} }
/** /**
* Put it all together and reset the file types list component. * Put it all together and reset the file types list component.
*/ */
FileType.Signature signature = new FileType.Signature(signatureBytes, offset, sigType); // RJCTODO: FileType.Signature signature = new FileType.Signature(signatureBytes, offset, sigType);
FileType fileType = new FileType(typeName, signature, filesSetName, this.postHitCheckBox.isSelected()); FileType fileType = new FileType(typeName, signature, filesSetName, this.postHitCheckBox.isSelected());
this.fileTypes.put(typeName, fileType); this.fileTypes.put(typeName, fileType);
this.setFileTypesListModel(); this.setFileTypesListModel();
@ -461,7 +432,6 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
this.filesSetNameTextField.setEnabled(this.postHitCheckBox.isSelected()); this.filesSetNameTextField.setEnabled(this.postHitCheckBox.isSelected());
}//GEN-LAST:event_postHitCheckBoxActionPerformed }//GEN-LAST:event_postHitCheckBoxActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton deleteTypeButton; private javax.swing.JButton deleteTypeButton;
private javax.swing.JLabel filesSetNameLabel; private javax.swing.JLabel filesSetNameLabel;

View File

@ -26,14 +26,7 @@
<xs:sequence> <xs:sequence>
<xs:element name="bytes" type="stringType"/> <xs:element name="bytes" type="stringType"/>
<xs:element name="offset" type="xs:nonNegativeInteger"/> <xs:element name="offset" type="xs:nonNegativeInteger"/>
<xs:attribute name="type" type="sigInterpretationType"/> <xs:attribute name="type" type="sigInterpretationType" use="required"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="filesSetType">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:attribute name="alert" type="xs:boolean"/>
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
@ -41,7 +34,8 @@
<xs:sequence> <xs:sequence>
<xs:element name="mimetype" type="verbatimStringType"/> <xs:element name="mimetype" type="verbatimStringType"/>
<xs:element name="signature" type="signatureType"/> <xs:element name="signature" type="signatureType"/>
<xs:element name="filesset" type="filesSetType"/> <xs:element minOccurs="0" maxOccurs="1" name="filesset" type="stringType"/>
<xs:attribute name="alert" type="xs:boolean" use="required"/>
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>

View File

@ -5,7 +5,7 @@
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this schemaFile except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.modules.filetypeid; package org.sleuthkit.autopsy.modules.filetypeid;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.nio.file.Path; import java.nio.file.Path;
@ -34,17 +35,16 @@ import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import javax.xml.bind.DatatypeConverter; import javax.xml.bind.DatatypeConverter;
import org.openide.util.Exceptions; import javax.xml.transform.TransformerException;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil; import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature; import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
/** /**
* Manages user-defined schemaFile types characterized by MIME type, signature, * Manages user-defined file types characterized by MIME type, signature, and
* and optional membership in an interesting files set. * optional membership in an interesting files set.
*/ */
final class UserDefinedFileTypesManager { final class UserDefinedFileTypesManager {
@ -65,35 +65,34 @@ final class UserDefinedFileTypesManager {
private static UserDefinedFileTypesManager instance; private static UserDefinedFileTypesManager instance;
/** /**
* Predefined schemaFile types are stored in this mapping of MIME types to * Predefined file types are stored in this mapping of MIME types to file
* schemaFile types. Access to this map is guarded by the intrinsic lock of * types. Access to this map is guarded by the intrinsic lock of the
* the user-defined schemaFile types manager for thread-safety. * user-defined file types manager for thread-safety.
*/ */
private final Map<String, FileType> predefinedFileTypes = new HashMap<>(); private final Map<String, FileType> predefinedFileTypes = new HashMap<>();
/** /**
* User-defined schemaFile types to be persisted to the user-defined * File types to be persisted to the user-defined file type definitions file
* schemaFile type definitions schemaFile are stored in this mapping of * are stored in this mapping of MIME types to file types. Access to this
* schemaFile type names to schemaFile types. Access to this map is guarded * map is guarded by the intrinsic lock of the user-defined file types
* by the intrinsic lock of the user-defined schemaFile types manager for * manager for thread-safety.
* thread-safety.
*/ */
private final Map<String, FileType> userDefinedFileTypes = new HashMap<>(); private final Map<String, FileType> userDefinedFileTypes = new HashMap<>();
/** /**
* The combined set of user-defined schemaFile types and schemaFile types * The combined set of user-defined file types and file types predefined by
* predefined by Autopsy are stored in this mapping of MIME types to * Autopsy are stored in this mapping of MIME types to file types. This is
* schemaFile types. This is the current working set of schemaFile types. * the current working set of file types. Access to this map is guarded by
* Access to this map is guarded by the intrinsic lock of the user-defined * the intrinsic lock of the user-defined file types manager for
* schemaFile types manager for thread-safety. * thread-safety.
*/ */
private final Map<String, FileType> fileTypes = new HashMap<>(); private final Map<String, FileType> fileTypes = new HashMap<>();
/** /**
* Gets the manager of user-defined schemaFile types characterized by MIME * Gets the manager of user-defined file types characterized by MIME type,
* type, signature, and optional membership in an interesting files set. * signature, and optional membership in an interesting files set.
* *
* @return The user-defined schemaFile types manager singleton. * @return The user-defined file types manager singleton.
*/ */
synchronized static UserDefinedFileTypesManager getInstance() { synchronized static UserDefinedFileTypesManager getInstance() {
if (UserDefinedFileTypesManager.instance == null) { if (UserDefinedFileTypesManager.instance == null) {
@ -103,8 +102,8 @@ final class UserDefinedFileTypesManager {
} }
/** /**
* Creates a manager of user-defined schemaFile types characterized by MIME * Creates a manager of user-defined file types characterized by MIME type,
* type, signature, and optional membership in an interesting files set. * signature, and optional membership in an interesting files set.
*/ */
private UserDefinedFileTypesManager() { private UserDefinedFileTypesManager() {
/** /**
@ -116,11 +115,11 @@ final class UserDefinedFileTypesManager {
} }
/** /**
* Adds the predefined schemaFile types to the in-memory mappings of MIME * Adds the predefined file types to the in-memory mappings of MIME types to
* types to schemaFile types. * file types.
*/ */
private void loadPredefinedFileTypes() { private void loadPredefinedFileTypes() {
// RJCTODO: Remove test schemaFile type. // RJCTODO: Remove test file type.
/** /**
* Create a file type that should match $MBR in Small2 image. * Create a file type that should match $MBR in Small2 image.
*/ */
@ -130,7 +129,7 @@ final class UserDefinedFileTypesManager {
/** /**
* Create a file type that should match test.txt in the Small2 image. * Create a file type that should match test.txt in the Small2 image.
*/ */
// RJCTODO: Remove test schemaFile type. // RJCTODO: Remove test file type.
try { try {
fileType = new FileType("predefinedASCII", new Signature("hello".getBytes(UserDefinedFileTypesManager.ASCII_ENCODING), 0L, FileType.Signature.Type.ASCII), "predefinedASCII", true); fileType = new FileType("predefinedASCII", new Signature("hello".getBytes(UserDefinedFileTypesManager.ASCII_ENCODING), 0L, FileType.Signature.Type.ASCII), "predefinedASCII", true);
this.addPredefinedFileType(fileType); this.addPredefinedFileType(fileType);
@ -150,7 +149,7 @@ final class UserDefinedFileTypesManager {
// buf = buffer; // buf = buffer;
// } // }
// //
// // the xml detection in Tika tries to parse the entire schemaFile and throws exceptions // // the xml detection in Tika tries to parse the entire file and throws exceptions
// // for files that are not valid XML // // for files that are not valid XML
// try { // try {
// String tagHeader = new String(buf, 0, 5); // String tagHeader = new String(buf, 0, 5);
@ -173,10 +172,10 @@ final class UserDefinedFileTypesManager {
} }
/** /**
* Adds a schemaFile type to the the predefined schemaFile types and * Adds a predefined file type to the in-memory mappings of MIME types to
* combined schemaFile types maps. * file types.
* *
* @param fileType The schemaFile type to add. * @param fileType The file type to add.
*/ */
private void addPredefinedFileType(FileType fileType) { private void addPredefinedFileType(FileType fileType) {
this.predefinedFileTypes.put(fileType.getMimeType(), fileType); this.predefinedFileTypes.put(fileType.getMimeType(), fileType);
@ -184,15 +183,15 @@ final class UserDefinedFileTypesManager {
} }
/** /**
* Adds the user-defined schemaFile types to the in-memory mappings of MIME * Adds the user-defined file types to the in-memory mappings of MIME types
* types to schemaFile types. * to file types.
*/ */
private void loadUserDefinedFileTypes() { private void loadUserDefinedFileTypes() {
try { try {
String filePath = getFileTypeDefinitionsFilePath(UserDefinedFileTypesManager.USER_DEFINED_TYPE_DEFINITIONS_FILE); String filePath = getFileTypeDefinitionsFilePath(UserDefinedFileTypesManager.USER_DEFINED_TYPE_DEFINITIONS_FILE);
File file = new File(filePath); File file = new File(filePath);
if (file.exists() && file.canRead()) { if (file.exists() && file.canRead()) {
for (FileType fileType : XMLReader.readFileTypes(filePath)) { for (FileType fileType : XmlReader.readFileTypes(filePath)) {
this.addUserDefinedFileType(fileType); this.addUserDefinedFileType(fileType);
} }
} }
@ -208,10 +207,10 @@ final class UserDefinedFileTypesManager {
} }
/** /**
* Adds a schemaFile type to the the user-defined schemaFile types and * Adds a user-defined file type to the in-memory mappings of MIME types to
* combined schemaFile types maps. * file types.
* *
* @param fileType The schemaFile type to add. * @param fileType The file type to add.
*/ */
private void addUserDefinedFileType(FileType fileType) { private void addUserDefinedFileType(FileType fileType) {
this.userDefinedFileTypes.put(fileType.getMimeType(), fileType); this.userDefinedFileTypes.put(fileType.getMimeType(), fileType);
@ -219,10 +218,9 @@ final class UserDefinedFileTypesManager {
} }
/** /**
* Gets both the predefined and the user-defined schemaFile types. * Gets both the predefined and the user-defined file types.
* *
* @return A mapping of schemaFile type names to schemaFile types, possibly * @return A mapping of file type names to file types, possibly empty.
* empty.
*/ */
synchronized Map<String, FileType> getFileTypes() { synchronized Map<String, FileType> getFileTypes() {
/** /**
@ -233,10 +231,9 @@ final class UserDefinedFileTypesManager {
} }
/** /**
* Gets the user-defined schemaFile types. * Gets the user-defined file types.
* *
* @return A mapping of schemaFile type names to schemaFile types, possibly * @return A mapping of file type names to file types, possibly empty.
* empty.
*/ */
synchronized Map<String, FileType> getUserDefinedFileTypes() { synchronized Map<String, FileType> getUserDefinedFileTypes() {
/** /**
@ -247,22 +244,20 @@ final class UserDefinedFileTypesManager {
} }
/** /**
* Sets the user-defined schemaFile types. * Sets the user-defined file types.
* *
* @param newFileTypes A mapping of schemaFile type names to user-defined * @param newFileTypes A mapping of file type names to user-defined file
* schemaFile types. * types.
* @throws
* org.sleuthkit.autopsy.modules.filetypeid.UserDefinedFileTypesManager.UserDefinedFileTypesException
*/ */
synchronized void setUserDefinedFileTypes(Map<String, FileType> newFileTypes) throws UserDefinedFileTypesManager.UserDefinedFileTypesException { synchronized void setUserDefinedFileTypes(Map<String, FileType> newFileTypes) throws UserDefinedFileTypesManager.UserDefinedFileTypesException {
try { try {
/**
* Persist the user-defined file type definitions.
*/
String filePath = UserDefinedFileTypesManager.getFileTypeDefinitionsFilePath(UserDefinedFileTypesManager.USER_DEFINED_TYPE_DEFINITIONS_FILE); String filePath = UserDefinedFileTypesManager.getFileTypeDefinitionsFilePath(UserDefinedFileTypesManager.USER_DEFINED_TYPE_DEFINITIONS_FILE);
UserDefinedFileTypesManager.XMLWriter.writeFileTypes(newFileTypes.values(), filePath); UserDefinedFileTypesManager.XmlWriter.writeFileTypes(newFileTypes.values(), filePath);
} catch (ParserConfigurationException | IOException ex) { } catch (ParserConfigurationException | FileNotFoundException | UnsupportedEncodingException | TransformerException ex) {
UserDefinedFileTypesManager.logger.log(Level.SEVERE, "Failed to write file types file", ex);
throw new UserDefinedFileTypesManager.UserDefinedFileTypesException(ex.getLocalizedMessage()); // RJCTODO: Create a bundled message
} catch (IOException ex) {
UserDefinedFileTypesManager.logger.log(Level.SEVERE, "Failed to write file types file", ex); UserDefinedFileTypesManager.logger.log(Level.SEVERE, "Failed to write file types file", ex);
throw new UserDefinedFileTypesManager.UserDefinedFileTypesException(ex.getLocalizedMessage()); // RJCTODO: Create a bundled message throw new UserDefinedFileTypesManager.UserDefinedFileTypesException(ex.getLocalizedMessage()); // RJCTODO: Create a bundled message
} }
@ -286,10 +281,10 @@ final class UserDefinedFileTypesManager {
} }
/** /**
* Gets the absolute path of a schemaFile type definitions schemaFile. * Gets the absolute path of a file type definitions file.
* *
* @param fileName The name of the schemaFile. * @param fileName The name of the file.
* @return The absolute path to the schemaFile. * @return The absolute path to the file.
*/ */
private static String getFileTypeDefinitionsFilePath(String fileName) { private static String getFileTypeDefinitionsFilePath(String fileName) {
Path filePath = Paths.get(PlatformUtil.getUserConfigDirectory(), fileName); Path filePath = Paths.get(PlatformUtil.getUserConfigDirectory(), fileName);
@ -297,109 +292,133 @@ final class UserDefinedFileTypesManager {
} }
/** /**
* Provides a mechanism for writing a set of schemaFile type definitions to * Provides a mechanism for writing a set of file type definitions to an XML
* an XML schemaFile. * file.
*/ */
private static class XMLWriter { private static class XmlWriter {
/** /**
* Writes a set of schemaFile type definitions to an XML schemaFile. * Writes a set of file type definitions to an XML file.
* *
* @param signatures A collection of schemaFile types. * @param fileTypes A collection of file types.
* @param filePath The path to the destination schemaFile. * @param filePath The path to the destination file.
* @throws ParserConfigurationException
* @throws IOException
* @throws FileNotFoundException
* @throws UnsupportedEncodingException
* @throws TransformerException
*/ */
private static void writeFileTypes(Collection<FileType> fileTypes, String filePath) throws ParserConfigurationException, IOException { private static void writeFileTypes(Collection<FileType> fileTypes, String filePath) throws ParserConfigurationException, IOException, FileNotFoundException, UnsupportedEncodingException, TransformerException {
Document doc = XMLUtil.createDoc(); Document doc = XMLUtil.createDocument();
Element fileTypesElem = doc.createElement(UserDefinedFileTypesManager.FILE_TYPES_TAG_NAME); Element fileTypesElem = doc.createElement(UserDefinedFileTypesManager.FILE_TYPES_TAG_NAME);
doc.appendChild(fileTypesElem); doc.appendChild(fileTypesElem);
for (FileType fileType : fileTypes) { for (FileType fileType : fileTypes) {
Element fileTypeElem = UserDefinedFileTypesManager.XMLWriter.createFileTypeElement(fileType, doc); Element fileTypeElem = UserDefinedFileTypesManager.XmlWriter.createFileTypeElement(fileType, doc);
fileTypesElem.appendChild(fileTypeElem); fileTypesElem.appendChild(fileTypeElem);
} }
if (!XMLUtil.saveDoc(HashDbManager.class, filePath, UserDefinedFileTypesManager.ENCODING_FOR_XML_FILE, doc)) { XMLUtil.saveDocument(doc, UserDefinedFileTypesManager.ENCODING_FOR_XML_FILE, filePath);
// RJCTODO: If time permits add XMLUtil that properly throws and deprecate this one
throw new IOException("Error saving user defined file types, see log for details"); //NON-NLS
}
} }
/** /**
* Creates an XML representation of a schemaFile type. * Creates an XML representation of a file type.
* *
* @param fileType The schemaFile type object. * @param fileType The file type object.
* @param doc The DOM document to use to create the XML. * @param doc The WC3 DOM object to use to create the XML.
* @return An XML element. * @return An XML element.
*/ */
private static Element createFileTypeElement(FileType fileType, Document doc) { private static Element createFileTypeElement(FileType fileType, Document doc) {
/**
* Create a file type element.
*/
Element fileTypeElem = doc.createElement(UserDefinedFileTypesManager.FILE_TYPE_TAG_NAME); Element fileTypeElem = doc.createElement(UserDefinedFileTypesManager.FILE_TYPE_TAG_NAME);
XmlWriter.addMimeTypeElement(fileType, fileTypeElem, doc);
XmlWriter.addSignatureElement(fileType, fileTypeElem, doc);
XmlWriter.addInterestingFilesSetElement(fileType, fileTypeElem, doc);
XmlWriter.addAlertAttribute(fileType, fileTypeElem);
return fileTypeElem;
}
/** /**
* Add a MIME type name child element. * Add a MIME type child element to a file type XML element.
*/ *
* @param fileType The file type to use as a content source.
* @param fileTypeElem The parent file type element.
* @param doc The WC3 DOM object to use to create the XML.
*/
private static void addMimeTypeElement(FileType fileType, Element fileTypeElem, Document doc) {
Element typeNameElem = doc.createElement(UserDefinedFileTypesManager.MIME_TYPE_TAG_NAME); Element typeNameElem = doc.createElement(UserDefinedFileTypesManager.MIME_TYPE_TAG_NAME);
typeNameElem.setTextContent(fileType.getMimeType()); typeNameElem.setTextContent(fileType.getMimeType());
fileTypeElem.appendChild(typeNameElem); fileTypeElem.appendChild(typeNameElem);
}
/** /**
* Add a signature child element with a type attribute. * Add a signature child element to a file type XML element.
*/ *
* @param fileType The file type to use as a content source.
* @param fileTypeElem The parent file type element.
* @param doc The WC3 DOM object to use to create the XML.
*/
private static void addSignatureElement(FileType fileType, Element fileTypeElem, Document doc) {
Signature signature = fileType.getSignature(); Signature signature = fileType.getSignature();
Element signatureElem = doc.createElement(UserDefinedFileTypesManager.SIGNATURE_TAG_NAME); Element signatureElem = doc.createElement(UserDefinedFileTypesManager.SIGNATURE_TAG_NAME);
signatureElem.setAttribute(UserDefinedFileTypesManager.SIGNATURE_TYPE_ATTRIBUTE, signature.getType().toString());
fileTypeElem.appendChild(signatureElem);
/**
* Add a bytes child element to the signature element.
*/
Element bytesElem = doc.createElement(UserDefinedFileTypesManager.BYTES_TAG_NAME); Element bytesElem = doc.createElement(UserDefinedFileTypesManager.BYTES_TAG_NAME);
bytesElem.setTextContent(DatatypeConverter.printHexBinary(signature.getSignatureBytes())); bytesElem.setTextContent(DatatypeConverter.printHexBinary(signature.getSignatureBytes()));
signatureElem.appendChild(bytesElem); signatureElem.appendChild(bytesElem);
/**
* Add an offset child element to the signature element.
*/
Element offsetElem = doc.createElement(UserDefinedFileTypesManager.OFFSET_TAG_NAME); Element offsetElem = doc.createElement(UserDefinedFileTypesManager.OFFSET_TAG_NAME);
offsetElem.setTextContent(DatatypeConverter.printLong(signature.getOffset())); offsetElem.setTextContent(DatatypeConverter.printLong(signature.getOffset()));
signatureElem.appendChild(offsetElem); signatureElem.appendChild(offsetElem);
/** signatureElem.setAttribute(UserDefinedFileTypesManager.SIGNATURE_TYPE_ATTRIBUTE, signature.getType().toString());
* Add a files set child element with an alert attribute. fileTypeElem.appendChild(signatureElem);
*/ }
/**
* Add an interesting files set element to a file type XML element.
*
* @param fileType The file type to use as a content source.
* @param fileTypeElem The parent file type element.
* @param doc The WC3 DOM object to use to create the XML.
*/
private static void addInterestingFilesSetElement(FileType fileType, Element fileTypeElem, Document doc) {
Element filesSetElem = doc.createElement(UserDefinedFileTypesManager.INTERESTING_FILES_SET_TAG_NAME); Element filesSetElem = doc.createElement(UserDefinedFileTypesManager.INTERESTING_FILES_SET_TAG_NAME);
filesSetElem.setTextContent(fileType.getFilesSetName()); filesSetElem.setTextContent(fileType.getFilesSetName());
filesSetElem.setAttribute(UserDefinedFileTypesManager.ALERT_ATTRIBUTE, Boolean.toString(fileType.alertOnMatch()));
fileTypeElem.appendChild(filesSetElem); fileTypeElem.appendChild(filesSetElem);
return fileTypeElem;
} }
/**
* Add an alert attribute to a file type XML element.
*
* @param fileType The file type to use as a content source.
* @param fileTypeElem The parent file type element.
*/
private static void addAlertAttribute(FileType fileType, Element fileTypeElem) {
fileTypeElem.setAttribute(UserDefinedFileTypesManager.ALERT_ATTRIBUTE, Boolean.toString(fileType.alertOnMatch()));
}
} }
/** /**
* Provides a mechanism for reading a set of schemaFile type definitions * Provides a mechanism for reading a set of file type definitions from an
* from an XML schemaFile. * XML file.
*/ */
private static class XMLReader { private static class XmlReader {
/** /**
* Reads a set of schemaFile type definitions from an XML schemaFile. * Reads a set of file type definitions from an XML file.
* *
* @param filePath The path to the XML schemaFile. * @param filePath The path to the XML file.
* @return A collection of schemaFile types read from the XML * @return A collection of file types read from the XML file.
* schemaFile.
*/ */
private static List<FileType> readFileTypes(String filePath) throws IOException, ParserConfigurationException, SAXException { private static List<FileType> readFileTypes(String filePath) throws IOException, ParserConfigurationException, SAXException {
List<FileType> fileTypes = new ArrayList<>(); List<FileType> fileTypes = new ArrayList<>();
Path schemaFilePath = Paths.get(PlatformUtil.getUserConfigDirectory(), UserDefinedFileTypesManager.FILE_TYPE_DEFINITIONS_SCHEMA_FILE); Path schemaFilePath = Paths.get(PlatformUtil.getUserConfigDirectory(), UserDefinedFileTypesManager.FILE_TYPE_DEFINITIONS_SCHEMA_FILE);
Document doc = XMLUtil.loadAndValidateDoc(UserDefinedFileTypesManager.XMLReader.class, filePath, schemaFilePath.toAbsolutePath().toString()); Document doc = XMLUtil.loadDocument(filePath, UserDefinedFileTypesManager.XmlReader.class, schemaFilePath.toAbsolutePath().toString());
if (doc != null) { if (doc != null) {
Element fileTypesElem = doc.getDocumentElement(); Element fileTypesElem = doc.getDocumentElement();
if (fileTypesElem != null && fileTypesElem.getNodeName().equals(UserDefinedFileTypesManager.FILE_TYPES_TAG_NAME)) { if (fileTypesElem != null && fileTypesElem.getNodeName().equals(UserDefinedFileTypesManager.FILE_TYPES_TAG_NAME)) {
NodeList fileTypeElems = fileTypesElem.getElementsByTagName(UserDefinedFileTypesManager.FILE_TYPE_TAG_NAME); NodeList fileTypeElems = fileTypesElem.getElementsByTagName(UserDefinedFileTypesManager.FILE_TYPE_TAG_NAME);
for (int i = 0; i < fileTypeElems.getLength(); ++i) { for (int i = 0; i < fileTypeElems.getLength(); ++i) {
Element fileTypeElem = (Element) fileTypeElems.item(i); Element fileTypeElem = (Element) fileTypeElems.item(i);
FileType fileType = UserDefinedFileTypesManager.XMLReader.parseFileType(fileTypeElem); FileType fileType = XmlReader.parseFileType(fileTypeElem);
fileTypes.add(fileType); fileTypes.add(fileType);
} }
} }
@ -408,94 +427,99 @@ final class UserDefinedFileTypesManager {
} }
/** /**
* Parse a schemaFile type definition from a schemaFile type XML * Gets a file type definition from a file type XML element.
* element.
* *
* @param fileTypeElem The XML element. * @param fileTypeElem The XML element.
* @return A schemaFile type object. * @return A file type object.
* @throws * @throws IllegalArgumentException
* @throws NumberFormatException
*/ */
private static FileType parseFileType(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException { private static FileType parseFileType(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException {
/** String mimeType = XmlReader.parseMimeType(fileTypeElem);
* Get the mime type child element. Signature signature = XmlReader.parseSignature(fileTypeElem);
*/ String filesSetName = XmlReader.parseInterestingFilesSet(fileTypeElem);
String mimeType = UserDefinedFileTypesManager.getChildElementTextContent(fileTypeElem, UserDefinedFileTypesManager.MIME_TYPE_TAG_NAME); boolean alert = XmlReader.parseAlert(fileTypeElem);
return new FileType(mimeType, signature, filesSetName, alert);
}
/** /**
* Get the signature child element. * Gets the MIME type from a file type XML element.
*/ *
* @param fileTypeElem The element
* @return A MIME type string.
*/
private static String parseMimeType(Element fileTypeElem) {
return getChildElementTextContent(fileTypeElem, UserDefinedFileTypesManager.MIME_TYPE_TAG_NAME);
}
/**
* Gets the signature from a file type XML element.
*
* @param fileTypeElem The XML element.
* @return The signature.
*/
private static Signature parseSignature(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException {
NodeList signatureElems = fileTypeElem.getElementsByTagName(UserDefinedFileTypesManager.SIGNATURE_TAG_NAME); NodeList signatureElems = fileTypeElem.getElementsByTagName(UserDefinedFileTypesManager.SIGNATURE_TAG_NAME);
Element signatureElem = (Element) signatureElems.item(0); Element signatureElem = (Element) signatureElems.item(0);
/**
* Get the signature (interpretation) type attribute from the
* signature child element.
*/
String sigTypeAttribute = signatureElem.getAttribute(UserDefinedFileTypesManager.SIGNATURE_TYPE_ATTRIBUTE); String sigTypeAttribute = signatureElem.getAttribute(UserDefinedFileTypesManager.SIGNATURE_TYPE_ATTRIBUTE);
Signature.Type signatureType = Signature.Type.valueOf(sigTypeAttribute); Signature.Type signatureType = Signature.Type.valueOf(sigTypeAttribute);
/** String sigBytesString = getChildElementTextContent(signatureElem, UserDefinedFileTypesManager.BYTES_TAG_NAME);
* Get the signature bytes.
*/
String sigBytesString = UserDefinedFileTypesManager.getChildElementTextContent(signatureElem, UserDefinedFileTypesManager.BYTES_TAG_NAME);
byte[] signatureBytes = DatatypeConverter.parseHexBinary(sigBytesString); byte[] signatureBytes = DatatypeConverter.parseHexBinary(sigBytesString);
/** String offsetString = getChildElementTextContent(signatureElem, UserDefinedFileTypesManager.OFFSET_TAG_NAME);
* Get the offset.
*/
String offsetString = UserDefinedFileTypesManager.getChildElementTextContent(signatureElem, UserDefinedFileTypesManager.OFFSET_TAG_NAME);
long offset = DatatypeConverter.parseLong(offsetString); long offset = DatatypeConverter.parseLong(offsetString);
/** return new Signature(signatureBytes, offset, signatureType);
* Get the interesting files set element. }
*/
/**
* Gets the interesting files set name from a file type XML element.
*
* @param fileTypeElem The XML element.
* @return The files set name, possibly empty.
*/
private static String parseInterestingFilesSet(Element fileTypeElem) {
String filesSetName = "";
NodeList filesSetElems = fileTypeElem.getElementsByTagName(UserDefinedFileTypesManager.INTERESTING_FILES_SET_TAG_NAME); NodeList filesSetElems = fileTypeElem.getElementsByTagName(UserDefinedFileTypesManager.INTERESTING_FILES_SET_TAG_NAME);
Element filesSetElem = (Element) filesSetElems.item(0); if (filesSetElems.getLength() > 0) {
String filesSetName = filesSetElem.getTextContent(); Element filesSetElem = (Element) filesSetElems.item(0);
filesSetName = filesSetElem.getTextContent();
/** }
* Get the alert attribute from the interesting files set element. return filesSetName;
*/
String alertAttribute = filesSetElem.getAttribute(UserDefinedFileTypesManager.ALERT_ATTRIBUTE);
boolean alert = Boolean.parseBoolean(alertAttribute);
/**
* Put it all together.
*/
Signature signature = new Signature(signatureBytes, offset, signatureType);
return new FileType(mimeType, signature, filesSetName, alert);
} }
}
/** /**
* Gets the text content of a single child element. Assumes the elements * Gets the alert attribute from a file type XML element.
* have already been validated. *
* * @param fileTypeElem The XML element.
* @param elem The parent element. * @return True or false;
* @param tagName The tag name of the child element. */
* @return The text content. private static boolean parseAlert(Element fileTypeElem) {
*/ String alertAttribute = fileTypeElem.getAttribute(UserDefinedFileTypesManager.ALERT_ATTRIBUTE);
private static String getChildElementTextContent(Element elem, String tagName) { return Boolean.parseBoolean(alertAttribute);
NodeList childElems = elem.getElementsByTagName(tagName);
Element childElem = (Element) childElems.item(0);
return childElem.getTextContent();
}
/**
* Used for throwing exceptions when parsing user-defined types XML elements
* and attributes.
*/
private static class InvalidXMLException extends Exception {
InvalidXMLException(String message) {
super(message);
} }
/**
* Gets the text content of a single child element.
*
* @param elem The parent element.
* @param tagName The tag name of the child element.
* @return The text content.
*/
private static String getChildElementTextContent(Element elem, String tagName) {
NodeList childElems = elem.getElementsByTagName(tagName);
Element childElem = (Element) childElems.item(0);
return childElem.getTextContent();
}
} }
/** /**
* Used to translate more implementation-details-specific exceptions (which * Used to translate more implementation-details-specific exceptions (which
* are logged by this class) into more generic exceptions for propagation to * are logged by this class) into more generic exceptions for propagation to
* clients of the user-defined schemaFile types manager. * clients of the user-defined file types manager.
*/ */
static class UserDefinedFileTypesException extends Exception { static class UserDefinedFileTypesException extends Exception {