1
2
3
4
5
6 package gov.nist.secauto.metaschema.databind.io.xml;
7
8 import com.ctc.wstx.api.WstxOutputProperties;
9 import com.ctc.wstx.stax.WstxOutputFactory;
10
11 import gov.nist.secauto.metaschema.core.model.IBoundObject;
12 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
13 import gov.nist.secauto.metaschema.databind.io.AbstractSerializer;
14 import gov.nist.secauto.metaschema.databind.io.SerializationFeature;
15 import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelAssembly;
16
17 import org.codehaus.stax2.XMLOutputFactory2;
18 import org.codehaus.stax2.XMLStreamWriter2;
19
20 import java.io.IOException;
21 import java.io.Writer;
22
23 import javax.xml.stream.XMLOutputFactory;
24 import javax.xml.stream.XMLStreamException;
25
26 import edu.umd.cs.findbugs.annotations.NonNull;
27
28 public class DefaultXmlSerializer<CLASS extends IBoundObject>
29 extends AbstractSerializer<CLASS> {
30 private XMLOutputFactory2 xmlOutputFactory;
31
32
33
34
35
36
37
38
39
40 public DefaultXmlSerializer(@NonNull IBoundDefinitionModelAssembly definition) {
41 super(definition);
42 }
43
44
45
46
47
48
49
50 @NonNull
51 protected final XMLOutputFactory2 getXMLOutputFactory() {
52 synchronized (this) {
53 if (xmlOutputFactory == null) {
54 xmlOutputFactory = (XMLOutputFactory2) XMLOutputFactory.newInstance();
55 assert xmlOutputFactory instanceof WstxOutputFactory;
56 xmlOutputFactory.configureForSpeed();
57 xmlOutputFactory.setProperty(WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL, true);
58 xmlOutputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
59 }
60 assert xmlOutputFactory != null;
61 return xmlOutputFactory;
62 }
63 }
64
65
66
67
68
69
70
71
72 protected void setXMLOutputFactory(@NonNull XMLOutputFactory2 xmlOutputFactory) {
73 synchronized (this) {
74 this.xmlOutputFactory = xmlOutputFactory;
75 }
76 }
77
78
79
80
81
82
83
84
85
86
87 @NonNull
88 protected final XMLStreamWriter2 newXMLStreamWriter(@NonNull Writer writer) throws IOException {
89 try {
90 return ObjectUtils.notNull((XMLStreamWriter2) getXMLOutputFactory().createXMLStreamWriter(writer));
91 } catch (XMLStreamException ex) {
92 throw new IOException(ex);
93 }
94 }
95
96 @Override
97 public void serialize(IBoundObject data, Writer writer) throws IOException {
98 XMLStreamWriter2 streamWriter = newXMLStreamWriter(writer);
99 IOException caughtException = null;
100 IBoundDefinitionModelAssembly definition = getDefinition();
101
102 MetaschemaXmlWriter xmlGenerator = new MetaschemaXmlWriter(streamWriter);
103
104 boolean serializeRoot = get(SerializationFeature.SERIALIZE_ROOT);
105 try {
106 if (serializeRoot) {
107 streamWriter.writeStartDocument("UTF-8", "1.0");
108 xmlGenerator.writeRoot(definition, data);
109 } else {
110 xmlGenerator.write(definition, data);
111 }
112
113 streamWriter.flush();
114
115 if (serializeRoot) {
116 streamWriter.writeEndDocument();
117 }
118 } catch (XMLStreamException ex) {
119 caughtException = new IOException(ex);
120 throw caughtException;
121 } finally {
122 try {
123 streamWriter.close();
124 } catch (XMLStreamException ex) {
125 if (caughtException == null) {
126 throw new IOException(ex);
127 }
128 caughtException.addSuppressed(ex);
129 throw caughtException;
130 }
131 }
132 }
133 }