All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.oxm.AbstractMarshaller Maven / Gradle / Ivy

There is a newer version: 1.5.10
Show newest version
/*
 * Copyright 2006 the original author or authors.
 *
 * 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.springframework.oxm;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.xml.transform.StaxResult;
import org.springframework.xml.transform.StaxSource;
import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.XMLReaderFactory;

/**
 * Abstract implementation of the Marshaller and Unmarshaller interface. This implementation
 * inspects the given Source or Result, and defers further handling to overridable template
 * methods.
 *
 * @author Arjen Poutsma
 * @since 1.0.0
 */
public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {

    /**
     * Logger available to subclasses.
     */
    protected final Log logger = LogFactory.getLog(getClass());

    private DocumentBuilderFactory documentBuilderFactory;

    /**
     * Marshals the object graph with the given root into the provided javax.xml.transform.Result.
     * 

* This implementation inspects the given result, and calls marshalDomResult, * marshalSaxResult, or marshalStreamResult. * * @param graph the root of the object graph to marshal * @param result the result to marshal to * @throws XmlMappingException if the given object cannot be marshalled to the result * @throws IOException if an I/O exception occurs * @throws IllegalArgumentException if result if neither a DOMResult, * SAXResult, StreamResult * @see #marshalDomResult(Object,javax.xml.transform.dom.DOMResult) * @see #marshalSaxResult(Object,javax.xml.transform.sax.SAXResult) * @see #marshalStreamResult(Object,javax.xml.transform.stream.StreamResult) */ public final void marshal(Object graph, Result result) throws XmlMappingException, IOException { if (result instanceof DOMResult) { marshalDomResult(graph, (DOMResult) result); } else if (result instanceof StaxResult) { marshalStaxResult(graph, (StaxResult) result); } else if (result instanceof SAXResult) { marshalSaxResult(graph, (SAXResult) result); } else if (result instanceof StreamResult) { marshalStreamResult(graph, (StreamResult) result); } else { throw new IllegalArgumentException("Unknown Result type: " + result.getClass()); } } /** * Unmarshals the given provided javax.xml.transform.Source into an object graph. *

* This implementation inspects the given result, and calls unmarshalDomSource, * unmarshalSaxSource, or unmarshalStreamSource. * * @param source the source to marshal from * @return the object graph * @throws XmlMappingException if the given source cannot be mapped to an object * @throws IOException if an I/O Exception occurs * @throws IllegalArgumentException if source is neither a DOMSource, a * SAXSource, nor a StreamSource * @see #unmarshalDomSource(javax.xml.transform.dom.DOMSource) * @see #unmarshalSaxSource(javax.xml.transform.sax.SAXSource) * @see #unmarshalStreamSource(javax.xml.transform.stream.StreamSource) */ public final Object unmarshal(Source source) throws XmlMappingException, IOException { if (source instanceof DOMSource) { return unmarshalDomSource((DOMSource) source); } else if (source instanceof StaxSource) { return unmarshalStaxSource((StaxSource) source); } else if (source instanceof SAXSource) { return unmarshalSaxSource((SAXSource) source); } else if (source instanceof StreamSource) { return unmarshalStreamSource((StreamSource) source); } else { throw new IllegalArgumentException("Unknown Source type: " + source.getClass()); } } /** * Create a DocumentBuilder that this marshaller will use for creating DOM documents when passed an * empty DOMSource. Can be overridden in subclasses, adding further initialization of the builder. * * @param factory the DocumentBuilderFactory that the DocumentBuilder should be created with * @return the DocumentBuilder * @throws javax.xml.parsers.ParserConfigurationException * if thrown by JAXP methods */ protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory) throws ParserConfigurationException { return factory.newDocumentBuilder(); } /** * Create a DocumentBuilder that this marshaller will use for creating DOM documents when passed an * empty DOMSource. The resulting DocumentBuilderFactory is cached, so this method will * only be called once. * * @return the DocumentBuilderFactory * @throws ParserConfigurationException if thrown by JAXP methods */ protected DocumentBuilderFactory createDocumentBuilderFactory() throws ParserConfigurationException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(false); factory.setNamespaceAware(true); return factory; } /** * Create a XMLReader that this marshaller will when passed an empty SAXSource. * * @return the XMLReader * @throws SAXException if thrown by JAXP methods */ protected XMLReader createXmlReader() throws SAXException { return XMLReaderFactory.createXMLReader(); } // // Marshalling // /** * Template method for handling DOMResults. This implementation defers to marshalDomNode. * * @param graph the root of the object graph to marshal * @param domResult the DOMResult * @throws XmlMappingException if the given object cannot be marshalled to the result * @throws IllegalArgumentException if the domResult is empty * @see #marshalDomNode(Object,org.w3c.dom.Node) */ protected void marshalDomResult(Object graph, DOMResult domResult) throws XmlMappingException { Assert.notNull(domResult.getNode(), "DOMResult does not contain Node"); marshalDomNode(graph, domResult.getNode()); } /** * Template method for handling StaxResults. This implementation defers to * marshalXMLSteamWriter, or marshalXMLEventConsumer, depending on what is contained in * the StaxResult. * * @param graph the root of the object graph to marshal * @param staxResult the StaxResult * @throws XmlMappingException if the given object cannot be marshalled to the result * @throws IllegalArgumentException if the domResult is empty * @see #marshalDomNode(Object,org.w3c.dom.Node) */ protected void marshalStaxResult(Object graph, StaxResult staxResult) throws XmlMappingException { if (staxResult.getXMLStreamWriter() != null) { marshalXmlStreamWriter(graph, staxResult.getXMLStreamWriter()); } else if (staxResult.getXMLEventWriter() != null) { marshalXmlEventWriter(graph, staxResult.getXMLEventWriter()); } else { throw new IllegalArgumentException("StaxResult contains neither XMLStreamWriter nor XMLEventConsumer"); } } /** * Template method for handling SAXResults. This implementation defers to * marshalSaxHandlers. * * @param graph the root of the object graph to marshal * @param saxResult the SAXResult * @throws XmlMappingException if the given object cannot be marshalled to the result * @see #marshalSaxHandlers(Object,org.xml.sax.ContentHandler,org.xml.sax.ext.LexicalHandler) */ protected void marshalSaxResult(Object graph, SAXResult saxResult) throws XmlMappingException { ContentHandler contentHandler = saxResult.getHandler(); Assert.notNull(contentHandler, "ContentHandler not set on SAXResult"); LexicalHandler lexicalHandler = saxResult.getLexicalHandler(); marshalSaxHandlers(graph, contentHandler, lexicalHandler); } /** * Template method for handling StreamResults. This implementation defers to * marshalOutputStream, or marshalWriter, depending on what is contained in the * StreamResult * * @param graph the root of the object graph to marshal * @param streamResult the StreamResult * @throws IOException if an I/O Exception occurs * @throws XmlMappingException if the given object cannot be marshalled to the result * @throws IllegalArgumentException if streamResult contains neither OutputStream nor * Writer. */ protected void marshalStreamResult(Object graph, StreamResult streamResult) throws XmlMappingException, IOException { if (streamResult.getOutputStream() != null) { marshalOutputStream(graph, streamResult.getOutputStream()); } else if (streamResult.getWriter() != null) { marshalWriter(graph, streamResult.getWriter()); } else { throw new IllegalArgumentException("StreamResult contains neither OutputStream nor Writer"); } } // // Unmarshalling // /** * Template method for handling DOMSources. This implementation defers to * unmarshalDomNode. If the given source is empty, an empty source Document will be * created as a placeholder. * * @param domSource the DOMSource * @return the object graph * @throws IllegalArgumentException if the domSource is empty * @throws XmlMappingException if the given source cannot be mapped to an object * @see #unmarshalDomNode(org.w3c.dom.Node) */ protected Object unmarshalDomSource(DOMSource domSource) throws XmlMappingException { if (domSource.getNode() == null) { try { if (documentBuilderFactory == null) { documentBuilderFactory = createDocumentBuilderFactory(); } DocumentBuilder documentBuilder = createDocumentBuilder(documentBuilderFactory); domSource.setNode(documentBuilder.newDocument()); } catch (ParserConfigurationException ex) { throw new UnmarshallingFailureException( "Could not create document placeholder for DOMSource: " + ex.getMessage(), ex); } } return unmarshalDomNode(domSource.getNode()); } /** * Template method for handling StaxSources. This implementation defers to * unmarshalXmlStreamReader, or unmarshalXmlEventReader. * * @param staxSource the StaxSource * @return the object graph * @throws XmlMappingException if the given source cannot be mapped to an object */ protected Object unmarshalStaxSource(StaxSource staxSource) throws XmlMappingException { if (staxSource.getXMLStreamReader() != null) { return unmarshalXmlStreamReader(staxSource.getXMLStreamReader()); } else if (staxSource.getXMLEventReader() != null) { return unmarshalXmlEventReader(staxSource.getXMLEventReader()); } else { throw new IllegalArgumentException("StaxSource contains neither XMLStreamReader nor XMLEventReader"); } } /** * Template method for handling SAXSources. This implementation defers to * unmarshalSaxReader. * * @param saxSource the SAXSource * @return the object graph * @throws XmlMappingException if the given source cannot be mapped to an object * @throws IOException if an I/O Exception occurs * @see #unmarshalSaxReader(org.xml.sax.XMLReader,org.xml.sax.InputSource) */ protected Object unmarshalSaxSource(SAXSource saxSource) throws XmlMappingException, IOException { if (saxSource.getXMLReader() == null) { try { saxSource.setXMLReader(createXmlReader()); } catch (SAXException ex) { throw new UnmarshallingFailureException("Could not create XMLReader for SAXSource: " + ex.getMessage(), ex); } } if (saxSource.getInputSource() == null) { saxSource.setInputSource(new InputSource()); } return unmarshalSaxReader(saxSource.getXMLReader(), saxSource.getInputSource()); } /** * Template method for handling StreamSources. This implementation defers to * unmarshalInputStream, or unmarshalReader. * * @param streamSource the StreamSource * @return the object graph * @throws IOException if an I/O exception occurs * @throws XmlMappingException if the given source cannot be mapped to an object */ protected Object unmarshalStreamSource(StreamSource streamSource) throws XmlMappingException, IOException { if (streamSource.getInputStream() != null) { return unmarshalInputStream(streamSource.getInputStream()); } else if (streamSource.getReader() != null) { return unmarshalReader(streamSource.getReader()); } else { throw new IllegalArgumentException("StreamSource contains neither InputStream nor Reader"); } } // // Abstract template methods // /** * Abstract template method for marshalling the given object graph to a DOM Node. *

* In practice, node is be a Document node, a DocumentFragment node, or a * Element node. In other words, a node that accepts children. * * @param graph the root of the object graph to marshal * @param node The DOM node that will contain the result tree * @throws XmlMappingException if the given object cannot be marshalled to the DOM node * @see org.w3c.dom.Document * @see org.w3c.dom.DocumentFragment * @see org.w3c.dom.Element */ protected abstract void marshalDomNode(Object graph, Node node) throws XmlMappingException; /** * Abstract template method for marshalling the given object to a StAX XMLEventWriter. * * @param graph the root of the object graph to marshal * @param eventWriter the XMLEventWriter to write to * @throws XmlMappingException if the given object cannot be marshalled to the DOM node */ protected abstract void marshalXmlEventWriter(Object graph, XMLEventWriter eventWriter) throws XmlMappingException; /** * Abstract template method for marshalling the given object to a StAX XMLStreamWriter. * * @param graph the root of the object graph to marshal * @param streamWriter the XMLStreamWriter to write to * @throws XmlMappingException if the given object cannot be marshalled to the DOM node */ protected abstract void marshalXmlStreamWriter(Object graph, XMLStreamWriter streamWriter) throws XmlMappingException; /** * Abstract template method for marshalling the given object graph to a OutputStream. * * @param graph the root of the object graph to marshal * @param outputStream the OutputStream to write to * @throws XmlMappingException if the given object cannot be marshalled to the writer * @throws IOException if an I/O exception occurs */ protected abstract void marshalOutputStream(Object graph, OutputStream outputStream) throws XmlMappingException, IOException; /** * Abstract template method for marshalling the given object graph to a SAX ContentHandler. * * @param graph the root of the object graph to marshal * @param contentHandler the SAX ContentHandler * @param lexicalHandler the SAX2 LexicalHandler. Can be null. * @throws XmlMappingException if the given object cannot be marshalled to the handlers */ protected abstract void marshalSaxHandlers(Object graph, ContentHandler contentHandler, LexicalHandler lexicalHandler) throws XmlMappingException; /** * Abstract template method for marshalling the given object graph to a Writer. * * @param graph the root of the object graph to marshal * @param writer the Writer to write to * @throws XmlMappingException if the given object cannot be marshalled to the writer * @throws IOException if an I/O exception occurs */ protected abstract void marshalWriter(Object graph, Writer writer) throws XmlMappingException, IOException; /** * Abstract template method for unmarshalling from a given DOM Node. * * @param node The DOM node that contains the objects to be unmarshalled * @return the object graph * @throws XmlMappingException if the given DOM node cannot be mapped to an object */ protected abstract Object unmarshalDomNode(Node node) throws XmlMappingException; /** * Abstract template method for unmarshalling from a given Stax XMLEventReader. * * @param eventReader The XMLEventReader to read from * @return the object graph * @throws XmlMappingException if the given event reader cannot be converted to an object */ protected abstract Object unmarshalXmlEventReader(XMLEventReader eventReader) throws XmlMappingException; /** * Abstract template method for unmarshalling from a given Stax XMLStreamReader. * * @param streamReader The XMLStreamReader to read from * @return the object graph * @throws XmlMappingException if the given stream reader cannot be converted to an object */ protected abstract Object unmarshalXmlStreamReader(XMLStreamReader streamReader) throws XmlMappingException; /** * Abstract template method for unmarshalling from a given InputStream. * * @param inputStream the InputStreamStream to read from * @return the object graph * @throws XmlMappingException if the given stream cannot be converted to an object * @throws IOException if an I/O exception occurs */ protected abstract Object unmarshalInputStream(InputStream inputStream) throws XmlMappingException, IOException; /** * Abstract template method for unmarshalling from a given Reader. * * @param reader the Reader to read from * @return the object graph * @throws XmlMappingException if the given reader cannot be converted to an object * @throws IOException if an I/O exception occurs */ protected abstract Object unmarshalReader(Reader reader) throws XmlMappingException, IOException; /** * Abstract template method for unmarshalling using a given SAX XMLReader and * InputSource. * * @param xmlReader the SAX XMLReader to parse with * @param inputSource the input source to parse from * @return the object graph * @throws XmlMappingException if the given reader and input source cannot be converted to an object * @throws java.io.IOException if an I/O exception occurs */ protected abstract Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource) throws XmlMappingException, IOException; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy