1
2
3
4
5 package org.apache.maven.toolchain.v4;
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.toolchain.InputLocation;
27 import org.apache.maven.api.toolchain.InputLocationTracker;
28 import org.apache.maven.api.xml.XmlNode;
29 import org.apache.maven.internal.xml.XmlNodeBuilder;
30 import org.apache.maven.api.toolchain.TrackableBase;
31 import org.apache.maven.api.toolchain.PersistedToolchains;
32 import org.apache.maven.api.toolchain.ToolchainModel;
33 import org.apache.maven.api.toolchain.InputSource;
34 import org.codehaus.stax2.util.StreamWriterDelegate;
35
36 import static javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI;
37
38 @Generated
39 public class MavenToolchainsStaxWriter {
40
41
42
43
44
45
46
47
48 private static final String NAMESPACE = "http://maven.apache.org/TOOLCHAINS/1.2.0";
49
50
51
52
53 private static final String SCHEMA_LOCATION = "http://maven.apache.org/xsd/toolchains-1.2.0.xsd";
54
55
56
57
58 private String namespace = NAMESPACE;
59
60
61
62
63 private String schemaLocation = SCHEMA_LOCATION;
64
65
66
67
68 private String fileComment = null;
69
70 private boolean addLocationInformation = true;
71
72
73
74
75 protected Function<InputLocation, String> stringFormatter;
76
77
78
79
80
81
82
83
84
85
86 public void setNamespace(String namespace) {
87 this.namespace = Objects.requireNonNull(namespace);
88 }
89
90
91
92
93
94
95 public void setSchemaLocation(String schemaLocation) {
96 this.schemaLocation = Objects.requireNonNull(schemaLocation);
97 }
98
99
100
101
102
103
104 public void setFileComment(String fileComment) {
105 this.fileComment = fileComment;
106 }
107
108
109
110
111 public void setAddLocationInformation(boolean addLocationInformation) {
112 this.addLocationInformation = addLocationInformation;
113 }
114
115
116
117
118
119
120 public void setStringFormatter(Function<InputLocation, String> stringFormatter) {
121 this.stringFormatter = stringFormatter;
122 }
123
124
125
126
127
128
129
130
131 public void write(Writer writer, PersistedToolchains persistedToolchains) throws IOException, XMLStreamException {
132 XMLOutputFactory factory = new com.ctc.wstx.stax.WstxOutputFactory();
133 factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false);
134 factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL, true);
135 factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM, true);
136 XMLStreamWriter serializer = new IndentingXMLStreamWriter(factory.createXMLStreamWriter(writer));
137 serializer.writeStartDocument(persistedToolchains.getModelEncoding(), null);
138 writePersistedToolchains("toolchains", persistedToolchains, serializer);
139 serializer.writeEndDocument();
140 }
141
142
143
144
145
146
147
148
149 public void write(OutputStream stream, PersistedToolchains persistedToolchains) throws IOException, XMLStreamException {
150 XMLOutputFactory factory = new com.ctc.wstx.stax.WstxOutputFactory();
151 factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false);
152 factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL, true);
153 factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM, true);
154 XMLStreamWriter serializer = new IndentingXMLStreamWriter(factory.createXMLStreamWriter(stream, persistedToolchains.getModelEncoding()));
155 serializer.writeStartDocument(persistedToolchains.getModelEncoding(), null);
156 writePersistedToolchains("toolchains", persistedToolchains, serializer);
157 serializer.writeEndDocument();
158 }
159
160 private void writeTrackableBase(String tagName, TrackableBase trackableBase, XMLStreamWriter serializer)
161 throws IOException, XMLStreamException {
162 if (trackableBase != null) {
163 serializer.writeStartElement(namespace, tagName);
164 serializer.writeEndElement();
165 }
166 }
167
168 private void writePersistedToolchains(String tagName, PersistedToolchains persistedToolchains, XMLStreamWriter serializer)
169 throws IOException, XMLStreamException {
170 if (persistedToolchains != null) {
171 if (this.fileComment != null) {
172 serializer.writeCharacters("\n");
173 serializer.writeComment(this.fileComment);
174 serializer.writeCharacters("\n");
175 }
176 serializer.writeStartElement("", tagName, namespace);
177 serializer.writeNamespace("", namespace);
178 serializer.writeNamespace("xsi", W3C_XML_SCHEMA_INSTANCE_NS_URI);
179 serializer.writeAttribute(W3C_XML_SCHEMA_INSTANCE_NS_URI, "schemaLocation", namespace + " " + schemaLocation);
180 writeList("toolchains", true, persistedToolchains.getToolchains(), serializer, persistedToolchains,
181 t -> writeToolchainModel("toolchain", t, serializer));
182 serializer.writeEndElement();
183 }
184 }
185
186 private void writeToolchainModel(String tagName, ToolchainModel toolchainModel, XMLStreamWriter serializer)
187 throws IOException, XMLStreamException {
188 if (toolchainModel != null) {
189 serializer.writeStartElement(namespace, tagName);
190 writeTag("type", null, toolchainModel.getType(), serializer, toolchainModel);
191 writeProperties("provides", toolchainModel.getProvides(), serializer, toolchainModel);
192 writeDom(toolchainModel.getConfiguration(), serializer);
193 serializer.writeEndElement();
194 }
195 }
196
197 @FunctionalInterface
198 private interface ElementWriter<T> {
199 public void write(T t) throws IOException, XMLStreamException;
200 }
201
202 private <T> void writeList(String tagName, List<T> list, XMLStreamWriter serializer, InputLocationTracker locationTracker, ElementWriter<T> writer) throws IOException, XMLStreamException {
203 writeList(tagName, false, list, serializer, locationTracker, writer);
204 }
205
206 private <T> void writeList(String tagName, boolean flat, List<T> list, XMLStreamWriter serializer, InputLocationTracker locationTracker, ElementWriter<T> writer) throws IOException, XMLStreamException {
207 if (list != null && !list.isEmpty()) {
208 if (!flat) {
209 serializer.writeStartElement(namespace, tagName);
210 }
211 int index = 0;
212 InputLocation location = locationTracker != null ? locationTracker.getLocation(tagName) : null;
213 for (T t : list) {
214 writer.write(t);
215 writeLocationTracking(location, Integer.valueOf(index++), serializer);
216 }
217 if (!flat) {
218 serializer.writeEndElement();
219 }
220 }
221 }
222
223 private <T> void writeProperties(String tagName, Map<String, String> props, XMLStreamWriter serializer, InputLocationTracker locationTracker) throws IOException, XMLStreamException {
224 if (props != null && !props.isEmpty()) {
225 serializer.writeStartElement(namespace, tagName);
226 InputLocation location = locationTracker != null ? locationTracker.getLocation(tagName) : null;
227 for (Map.Entry<String, String> entry : props.entrySet()) {
228 String key = entry.getKey();
229 writeTag(key, null, entry.getValue(), serializer, null);
230 writeLocationTracking(location, key, serializer);
231 }
232 serializer.writeEndElement();
233 }
234 }
235
236 private void writeDom(XmlNode dom, XMLStreamWriter serializer) throws IOException, XMLStreamException {
237 if (dom != null) {
238 serializer.writeStartElement(namespace, dom.getName());
239 for (Map.Entry<String, String> attr : dom.getAttributes().entrySet()) {
240 if (attr.getKey().startsWith("xml:")) {
241 serializer.writeAttribute("http://www.w3.org/XML/1998/namespace",
242 attr.getKey().substring(4), attr.getValue());
243 } else {
244 serializer.writeAttribute(attr.getKey(), attr.getValue());
245 }
246 }
247 for (XmlNode child : dom.getChildren()) {
248 writeDom(child, serializer);
249 }
250 String value = dom.getValue();
251 if (value != null) {
252 serializer.writeCharacters(value);
253 }
254 serializer.writeEndElement();
255 if (addLocationInformation && dom.getInputLocation() instanceof InputLocation && dom.getChildren().isEmpty()) {
256 serializer.writeComment(toString((InputLocation) dom.getInputLocation()));
257 }
258 }
259 }
260
261 private void writeTag(String tagName, String defaultValue, String value, XMLStreamWriter serializer, InputLocationTracker locationTracker) throws IOException, XMLStreamException {
262 if (value != null && !Objects.equals(defaultValue, value)) {
263 serializer.writeStartElement(namespace, tagName);
264 serializer.writeCharacters(value);
265 serializer.writeEndElement();
266 writeLocationTracking(locationTracker, tagName, serializer);
267 }
268 }
269
270 private void writeAttr(String attrName, String value, XMLStreamWriter serializer) throws IOException, XMLStreamException {
271 if (value != null) {
272 serializer.writeAttribute(attrName, value);
273 }
274 }
275
276
277
278
279
280
281
282
283
284 protected void writeLocationTracking(InputLocationTracker locationTracker, Object key, XMLStreamWriter serializer) throws IOException, XMLStreamException {
285 if (addLocationInformation) {
286 InputLocation location = (locationTracker == null) ? null : locationTracker.getLocation(key);
287 if (location != null) {
288 serializer.writeComment(toString(location));
289 }
290 }
291 }
292
293
294
295
296
297
298
299 protected String toString(InputLocation location) {
300 if (stringFormatter != null) {
301 return stringFormatter.apply(location);
302 }
303 if (location.getSource() != null) {
304 return ' ' + location.getSource().toString() + ':' + location.getLineNumber() + ' ';
305 } else {
306 return " " + location.getLineNumber() + " ";
307 }
308 }
309
310 static class IndentingXMLStreamWriter extends StreamWriterDelegate {
311
312 int depth = 0;
313 boolean hasChildren = false;
314
315 public IndentingXMLStreamWriter(XMLStreamWriter parent) {
316 super(parent);
317 }
318
319 @Override
320 public void writeEmptyElement(String localName) throws XMLStreamException {
321 indent();
322 super.writeEmptyElement(localName);
323 hasChildren = true;
324 }
325
326 @Override
327 public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
328 indent();
329 super.writeEmptyElement(namespaceURI, localName);
330 hasChildren = true;
331 }
332
333 @Override
334 public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
335 indent();
336 super.writeEmptyElement(prefix, localName, namespaceURI);
337 hasChildren = true;
338 }
339
340 @Override
341 public void writeStartElement(String localName) throws XMLStreamException {
342 indent();
343 super.writeStartElement(localName);
344 depth++;
345 hasChildren = false;
346 }
347
348 @Override
349 public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
350 indent();
351 super.writeStartElement(namespaceURI, localName);
352 depth++;
353 hasChildren = false;
354 }
355
356 @Override
357 public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
358 indent();
359 super.writeStartElement(prefix, localName, namespaceURI);
360 depth++;
361 hasChildren = false;
362 }
363
364 @Override
365 public void writeEndElement() throws XMLStreamException {
366 depth--;
367 if (hasChildren) {
368 indent();
369 }
370 super.writeEndElement();
371 hasChildren = true;
372 }
373
374 private void indent() throws XMLStreamException {
375 super.writeCharacters("\n");
376 for (int i = 0; i < depth; i++) {
377 super.writeCharacters(" ");
378 }
379 }
380 }
381 }