Skip to content
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.fasterxml.jackson.dataformat.xml;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import javax.xml.stream.*;

Expand Down Expand Up @@ -517,6 +519,34 @@ public ToXmlGenerator createGenerator(OutputStream out, JsonEncoding enc) throws
_generatorFeatures, _xmlGeneratorFeatures,
_objectCodec, _createXmlWriter(ctxt, out), _nameProcessor);
}

/**
* Method for constructing a {@link ToXmlGenerator} for writing XML content
* using specified output stream.
* Encoding to use must be specified.
*<p>
* Underlying stream <b>is NOT owned</b> by the generator constructed,
* so that generator will NOT close the output stream when
* {@link ToXmlGenerator#close} is called (unless auto-closing
* feature,
* {@link com.fasterxml.jackson.core.JsonGenerator.Feature#AUTO_CLOSE_TARGET}
* is enabled).
* Using application needs to close it explicitly if this is the case.
*
* @param out OutputStream to use for writing JSON content
* @param encoding Character encoding to use
* @return a {@link ToXmlGenerator} instance
* @throws IOException
* @since 2.16
*/
public ToXmlGenerator createGenerator(OutputStream out, Charset encoding) throws IOException
{
// false -> we won't manage the stream unless explicitly directed to
final IOContext ctxt = _createContext(_createContentReference(out), false);
return new ToXmlGenerator(ctxt,
_generatorFeatures, _xmlGeneratorFeatures,
_objectCodec, _createXmlWriter(ctxt, out, encoding), _nameProcessor, encoding);
}

@Override
public ToXmlGenerator createGenerator(Writer out) throws IOException
Expand Down Expand Up @@ -689,10 +719,15 @@ protected JsonGenerator _createGenerator(Writer out, IOContext ctxt) throws IOEx
*/

protected XMLStreamWriter _createXmlWriter(IOContext ctxt, OutputStream out) throws IOException
{
return _createXmlWriter(ctxt, out, StandardCharsets.UTF_8);
}

protected final XMLStreamWriter _createXmlWriter(IOContext ctxt, OutputStream out, Charset encoding) throws IOException
{
XMLStreamWriter sw;
try {
sw = _xmlOutputFactory.createXMLStreamWriter(_decorate(ctxt, out), "UTF-8");
sw = _xmlOutputFactory.createXMLStreamWriter(_decorate(ctxt, out), encoding.name());
} catch (Exception e) {
throw new JsonGenerationException(e.getMessage(), e, null);
}
Expand Down
205 changes: 204 additions & 1 deletion src/main/java/com/fasterxml/jackson/dataformat/xml/XmlMapper.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
package com.fasterxml.jackson.dataformat.xml;

import java.io.DataOutput;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.text.DateFormat;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.exc.StreamWriteException;
import com.fasterxml.jackson.core.io.CharacterEscapes;
import com.fasterxml.jackson.core.io.DataOutputAsStream;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.core.util.ByteArrayBuilder;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.cfg.CoercionAction;
import com.fasterxml.jackson.databind.cfg.CoercionInputShape;
import com.fasterxml.jackson.databind.cfg.ContextAttributes;
import com.fasterxml.jackson.databind.cfg.MapperBuilder;
import com.fasterxml.jackson.databind.deser.BeanDeserializerFactory;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.type.LogicalType;
import com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser;
import com.fasterxml.jackson.dataformat.xml.deser.XmlDeserializationContext;
Expand Down Expand Up @@ -305,7 +317,7 @@ public void setXmlNameProcessor(XmlNameProcessor processor) {
public XmlFactory getFactory() {
return (XmlFactory) _jsonFactory;
}

public ObjectMapper configure(ToXmlGenerator.Feature f, boolean state) {
((XmlFactory)_jsonFactory).configure(f, state);
return this;
Expand Down Expand Up @@ -392,4 +404,195 @@ public void writeValue(XMLStreamWriter w0, Object value) throws IOException {
// NOTE: above call should do flush(); and we should NOT close here.
// Finally, 'g' has no buffers to release.
}

/**
* Method that can be used to serialize any Java value as
* a byte array.
*
* @param value value to serialize as XML bytes
* @param encoding character encoding for the XML output
* @return byte array representing the XML output
* @throws JsonProcessingException
* @since 2.16
*/
public byte[] writeValueAsBytes(Object value, Charset encoding) throws JsonProcessingException {
try (ByteArrayBuilder bb = new ByteArrayBuilder(_jsonFactory._getBufferRecycler())) {
_writeValueAndClose(createGenerator(bb, encoding), value);
final byte[] result = bb.toByteArray();
bb.release();
return result;
} catch (JsonProcessingException e) { // to support [JACKSON-758]
throw e;
} catch (IOException e) { // shouldn't really happen, but is declared as possibility so:
throw JsonMappingException.fromUnexpectedIOE(e);
}
}

/**
* Method that can be used to serialize any Java value as
* XML output, written to File provided.
*
* @param resultFile the file to write to
* @param value the value to serialize
* @param encoding character encoding for the XML output
* @throws IOException
* @throws StreamWriteException
* @throws DatabindException
* @since 2.16
*/
public void writeValue(File resultFile, Object value, Charset encoding)
throws IOException, StreamWriteException, DatabindException
{
_writeValueAndClose(createGenerator(resultFile, encoding), value);
}

/**
* Method that can be used to serialize any Java value as
* JSON output, using output stream provided (using encoding
* {@link JsonEncoding#UTF8}).
*<p>
* Note: method does not close the underlying stream explicitly
* here; however, {@link JsonFactory} this mapper uses may choose
* to close the stream depending on its settings (by default,
* it will try to close it when {@link JsonGenerator} we construct
* is closed).
*
* @since 2.16
*/
public void writeValue(OutputStream out, Object value, Charset encoding)
throws IOException, StreamWriteException, DatabindException
{
_writeValueAndClose(createGenerator(out, encoding), value);
}

public void writeValue(DataOutput out, Object value, Charset encoding)
throws IOException, StreamWriteException, DatabindException
{
_writeValueAndClose(createGenerator(out, encoding), value);
}

@Override
public ObjectWriter writer() {
return new XmlWriter(super.writer());
}

@Override
public ObjectWriter writer(SerializationFeature feature) {
return new XmlWriter(super.writer(feature));
}

@Override
public ObjectWriter writer(SerializationFeature first, SerializationFeature... other) {
return new XmlWriter(super.writer(first, other));
}

@Override
public ObjectWriter writer(DateFormat df) {
return new XmlWriter(super.writer(df));
}

@Override
public ObjectWriter writerWithView(Class<?> serializationView) {
return new XmlWriter(super.writerWithView(serializationView));
}

@Override
public ObjectWriter writerFor(Class<?> rootType) {
return new XmlWriter(super.writerFor(rootType));
}

@Override
public ObjectWriter writerFor(TypeReference<?> rootType) {
return new XmlWriter(super.writerFor(rootType));
}

@Override
public ObjectWriter writerFor(JavaType rootType) {
return new XmlWriter(super.writerFor(rootType));
}

@Override
public ObjectWriter writer(PrettyPrinter pp) {
return new XmlWriter(super.writer(pp));
}

@Override
public ObjectWriter writerWithDefaultPrettyPrinter() {
return new XmlWriter(super.writerWithDefaultPrettyPrinter());
}

@Override
public ObjectWriter writer(FilterProvider filterProvider) {
return new XmlWriter(super.writer(filterProvider));
}

@Override
public ObjectWriter writer(FormatSchema schema) {
return new XmlWriter(super.writer(schema));
}

@Override
public ObjectWriter writer(Base64Variant defaultBase64) {
return new XmlWriter(super.writer(defaultBase64));
}

@Override
public ObjectWriter writer(CharacterEscapes escapes) {
return new XmlWriter(super.writer(escapes));
}

@Override
public ObjectWriter writer(ContextAttributes attrs) {
return new XmlWriter(super.writer(attrs));
}

/** @deprecated */
@Override
@Deprecated
public ObjectWriter writerWithType(Class<?> rootType) {
return new XmlWriter(super.writerWithType(rootType));
}

/** @deprecated */
@Override
@Deprecated
public ObjectWriter writerWithType(TypeReference<?> rootType) {
return new XmlWriter(super.writerWithType(rootType));
}

/** @deprecated */
@Override
@Deprecated
public ObjectWriter writerWithType(JavaType rootType) {
return new XmlWriter(super.writerWithType(rootType));
}

public static XmlWriter toXmlWriter(final ObjectWriter objectWriter) {
if (objectWriter instanceof XmlWriter) {
return (XmlWriter) objectWriter;
}
return new XmlWriter(objectWriter);
}

protected final JsonGenerator createGenerator(OutputStream out, Charset encoding) throws IOException {
this._assertNotNull("out", out);
JsonGenerator g = ((XmlFactory) _jsonFactory).createGenerator(out, encoding);
this._serializationConfig.initialize(g);
return g;
}

protected final JsonGenerator createGenerator(File outputFile, Charset encoding) throws IOException {
_assertNotNull("outputFile", outputFile);
JsonGenerator g = ((XmlFactory) _jsonFactory).createGenerator(
new FileOutputStream(outputFile), encoding);
_serializationConfig.initialize(g);
return g;
}

protected final JsonGenerator createGenerator(DataOutput out, Charset encoding) throws IOException {
this._assertNotNull("out", out);
JsonGenerator g = ((XmlFactory) _jsonFactory).createGenerator(new DataOutputAsStream(out), encoding);
this._serializationConfig.initialize(g);
return g;
}
}
Loading