1
2
3
4
5 package org.apache.maven.cli.internal.extension.io;
6
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.OutputStream;
10 import java.io.Reader;
11 import java.io.Writer;
12 import java.text.DateFormat;
13 import java.util.ArrayList;
14 import java.util.Date;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Objects;
19 import java.util.Properties;
20 import java.util.Set;
21 import java.util.function.Function;
22 import javax.xml.stream.XMLOutputFactory;
23 import javax.xml.stream.XMLStreamException;
24 import javax.xml.stream.XMLStreamWriter;
25 import org.apache.maven.api.annotations.Generated;
26 import org.apache.maven.api.xml.XmlNode;
27 import org.apache.maven.internal.xml.XmlNodeBuilder;
28 import org.apache.maven.cli.internal.extension.model.CoreExtensions;
29 import org.apache.maven.cli.internal.extension.model.CoreExtension;
30 import org.codehaus.stax2.util.StreamWriterDelegate;
31
32 import static javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI;
33
34 @Generated
35 public class CoreExtensionsStaxWriter {
36
37
38
39
40
41
42
43
44 private static final String NAMESPACE = "http://maven.apache.org/EXTENSIONS/1.2.0";
45
46
47
48
49 private static final String SCHEMA_LOCATION = "http://maven.apache.org/xsd/core-extensions-1.2.0.xsd";
50
51
52
53
54 private String namespace = NAMESPACE;
55
56
57
58
59 private String schemaLocation = SCHEMA_LOCATION;
60
61
62
63
64 private String fileComment = null;
65
66
67
68
69
70
71
72
73
74
75 public void setNamespace(String namespace) {
76 this.namespace = Objects.requireNonNull(namespace);
77 }
78
79
80
81
82
83
84 public void setSchemaLocation(String schemaLocation) {
85 this.schemaLocation = Objects.requireNonNull(schemaLocation);
86 }
87
88
89
90
91
92
93 public void setFileComment(String fileComment) {
94 this.fileComment = fileComment;
95 }
96
97
98
99
100
101
102
103
104 public void write(Writer writer, CoreExtensions coreExtensions) throws IOException, XMLStreamException {
105 XMLOutputFactory factory = new com.ctc.wstx.stax.WstxOutputFactory();
106 factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false);
107 factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL, true);
108 factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM, true);
109 XMLStreamWriter serializer = new IndentingXMLStreamWriter(factory.createXMLStreamWriter(writer));
110 serializer.writeStartDocument(coreExtensions.getModelEncoding(), null);
111 writeCoreExtensions("extensions", coreExtensions, serializer);
112 serializer.writeEndDocument();
113 }
114
115
116
117
118
119
120
121
122 public void write(OutputStream stream, CoreExtensions coreExtensions) throws IOException, XMLStreamException {
123 XMLOutputFactory factory = new com.ctc.wstx.stax.WstxOutputFactory();
124 factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false);
125 factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL, true);
126 factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM, true);
127 XMLStreamWriter serializer = new IndentingXMLStreamWriter(factory.createXMLStreamWriter(stream, coreExtensions.getModelEncoding()));
128 serializer.writeStartDocument(coreExtensions.getModelEncoding(), null);
129 writeCoreExtensions("extensions", coreExtensions, serializer);
130 serializer.writeEndDocument();
131 }
132
133 private void writeCoreExtensions(String tagName, CoreExtensions coreExtensions, XMLStreamWriter serializer)
134 throws IOException, XMLStreamException {
135 if (coreExtensions != null) {
136 if (this.fileComment != null) {
137 serializer.writeCharacters("\n");
138 serializer.writeComment(this.fileComment);
139 serializer.writeCharacters("\n");
140 }
141 serializer.writeStartElement("", tagName, namespace);
142 serializer.writeNamespace("", namespace);
143 serializer.writeNamespace("xsi", W3C_XML_SCHEMA_INSTANCE_NS_URI);
144 serializer.writeAttribute(W3C_XML_SCHEMA_INSTANCE_NS_URI, "schemaLocation", namespace + " " + schemaLocation);
145 writeList("extensions", true, coreExtensions.getExtensions(), serializer,
146 t -> writeCoreExtension("extension", t, serializer));
147 serializer.writeEndElement();
148 }
149 }
150
151 private void writeCoreExtension(String tagName, CoreExtension coreExtension, XMLStreamWriter serializer)
152 throws IOException, XMLStreamException {
153 if (coreExtension != null) {
154 serializer.writeStartElement(namespace, tagName);
155 writeTag("groupId", null, coreExtension.getGroupId(), serializer);
156 writeTag("artifactId", null, coreExtension.getArtifactId(), serializer);
157 writeTag("version", null, coreExtension.getVersion(), serializer);
158 writeTag("classLoadingStrategy", "self-first", coreExtension.getClassLoadingStrategy(), serializer);
159 writeDom(coreExtension.getConfiguration(), serializer);
160 serializer.writeEndElement();
161 }
162 }
163
164 @FunctionalInterface
165 private interface ElementWriter<T> {
166 public void write(T t) throws IOException, XMLStreamException;
167 }
168
169 private <T> void writeList(String tagName, List<T> list, XMLStreamWriter serializer, ElementWriter<T> writer) throws IOException, XMLStreamException {
170 writeList(tagName, false, list, serializer, writer);
171 }
172
173 private <T> void writeList(String tagName, boolean flat, List<T> list, XMLStreamWriter serializer, ElementWriter<T> writer) throws IOException, XMLStreamException {
174 if (list != null && !list.isEmpty()) {
175 if (!flat) {
176 serializer.writeStartElement(namespace, tagName);
177 }
178 int index = 0;
179 for (T t : list) {
180 writer.write(t);
181 }
182 if (!flat) {
183 serializer.writeEndElement();
184 }
185 }
186 }
187
188 private <T> void writeProperties(String tagName, Map<String, String> props, XMLStreamWriter serializer) throws IOException, XMLStreamException {
189 if (props != null && !props.isEmpty()) {
190 serializer.writeStartElement(namespace, tagName);
191 for (Map.Entry<String, String> entry : props.entrySet()) {
192 String key = entry.getKey();
193 writeTag(key, null, entry.getValue(), serializer);
194 }
195 serializer.writeEndElement();
196 }
197 }
198
199 private void writeDom(XmlNode dom, XMLStreamWriter serializer) throws IOException, XMLStreamException {
200 if (dom != null) {
201 serializer.writeStartElement(namespace, dom.getName());
202 for (Map.Entry<String, String> attr : dom.getAttributes().entrySet()) {
203 if (attr.getKey().startsWith("xml:")) {
204 serializer.writeAttribute("http://www.w3.org/XML/1998/namespace",
205 attr.getKey().substring(4), attr.getValue());
206 } else {
207 serializer.writeAttribute(attr.getKey(), attr.getValue());
208 }
209 }
210 for (XmlNode child : dom.getChildren()) {
211 writeDom(child, serializer);
212 }
213 String value = dom.getValue();
214 if (value != null) {
215 serializer.writeCharacters(value);
216 }
217 serializer.writeEndElement();
218 }
219 }
220
221 private void writeTag(String tagName, String defaultValue, String value, XMLStreamWriter serializer) throws IOException, XMLStreamException {
222 if (value != null && !Objects.equals(defaultValue, value)) {
223 serializer.writeStartElement(namespace, tagName);
224 serializer.writeCharacters(value);
225 serializer.writeEndElement();
226 }
227 }
228
229 private void writeAttr(String attrName, String value, XMLStreamWriter serializer) throws IOException, XMLStreamException {
230 if (value != null) {
231 serializer.writeAttribute(attrName, value);
232 }
233 }
234
235 static class IndentingXMLStreamWriter extends StreamWriterDelegate {
236
237 int depth = 0;
238 boolean hasChildren = false;
239
240 public IndentingXMLStreamWriter(XMLStreamWriter parent) {
241 super(parent);
242 }
243
244 @Override
245 public void writeEmptyElement(String localName) throws XMLStreamException {
246 indent();
247 super.writeEmptyElement(localName);
248 hasChildren = true;
249 }
250
251 @Override
252 public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
253 indent();
254 super.writeEmptyElement(namespaceURI, localName);
255 hasChildren = true;
256 }
257
258 @Override
259 public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
260 indent();
261 super.writeEmptyElement(prefix, localName, namespaceURI);
262 hasChildren = true;
263 }
264
265 @Override
266 public void writeStartElement(String localName) throws XMLStreamException {
267 indent();
268 super.writeStartElement(localName);
269 depth++;
270 hasChildren = false;
271 }
272
273 @Override
274 public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
275 indent();
276 super.writeStartElement(namespaceURI, localName);
277 depth++;
278 hasChildren = false;
279 }
280
281 @Override
282 public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
283 indent();
284 super.writeStartElement(prefix, localName, namespaceURI);
285 depth++;
286 hasChildren = false;
287 }
288
289 @Override
290 public void writeEndElement() throws XMLStreamException {
291 depth--;
292 if (hasChildren) {
293 indent();
294 }
295 super.writeEndElement();
296 hasChildren = true;
297 }
298
299 private void indent() throws XMLStreamException {
300 super.writeCharacters("\n");
301 for (int i = 0; i < depth; i++) {
302 super.writeCharacters(" ");
303 }
304 }
305 }
306 }