package com.fasterxml.jackson.databind.ext;

import java.io.StringReader;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer;

Base for serializers that allows parsing DOM Documents from JSON Strings. Nominal type can be either Node or Document.
/** * Base for serializers that allows parsing DOM Documents from JSON Strings. * Nominal type can be either {@link org.w3c.dom.Node} or * {@link org.w3c.dom.Document}. */
public abstract class DOMDeserializer<T> extends FromStringDeserializer<T> { private static final long serialVersionUID = 1L; private final static DocumentBuilderFactory DEFAULT_PARSER_FACTORY; static { DocumentBuilderFactory parserFactory = DocumentBuilderFactory.newInstance(); // yup, only cave men do XML without recognizing namespaces... parserFactory.setNamespaceAware(true); // [databind#1279]: make sure external entities NOT expanded by default parserFactory.setExpandEntityReferences(false); // ... and in general, aim for "safety" try { parserFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); } catch(ParserConfigurationException pce) { // not much point to do anything; could log but... } catch (Error e) { // 14-Jul-2016, tatu: Not sure how or why, but during code coverage runs // (via Cobertura) we get `java.lang.AbstractMethodError` so... ignore that too } // [databind#2589] add two more settings just in case try { parserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); } catch (Throwable t) { } // as per previous one, nothing much to do try { parserFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); } catch (Throwable t) { } // as per previous one, nothing much to do DEFAULT_PARSER_FACTORY = parserFactory; } protected DOMDeserializer(Class<T> cls) { super(cls); } @Override public abstract T _deserialize(String value, DeserializationContext ctxt); protected final Document parse(String value) throws IllegalArgumentException { try { return documentBuilder().parse(new InputSource(new StringReader(value))); } catch (Exception e) { throw new IllegalArgumentException("Failed to parse JSON String as XML: "+e.getMessage(), e); } }
Overridable factory method used to create DocumentBuilder for parsing XML as DOM.
Since:2.7.6
/** * Overridable factory method used to create {@link DocumentBuilder} for parsing * XML as DOM. * * @since 2.7.6 */
protected DocumentBuilder documentBuilder() throws ParserConfigurationException { return DEFAULT_PARSER_FACTORY.newDocumentBuilder(); } /* /********************************************************** /* Concrete deserializers /********************************************************** */ public static class NodeDeserializer extends DOMDeserializer<Node> { private static final long serialVersionUID = 1L; public NodeDeserializer() { super(Node.class); } @Override public Node _deserialize(String value, DeserializationContext ctxt) throws IllegalArgumentException { return parse(value); } } public static class DocumentDeserializer extends DOMDeserializer<Document> { private static final long serialVersionUID = 1L; public DocumentDeserializer() { super(Document.class); } @Override public Document _deserialize(String value, DeserializationContext ctxt) throws IllegalArgumentException { return parse(value); } } }