1
2
3
4
5 package org.apache.maven.plugin.lifecycle.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.api.plugin.descriptor.lifecycle.LifecycleConfiguration;
29 import org.apache.maven.api.plugin.descriptor.lifecycle.Lifecycle;
30 import org.apache.maven.api.plugin.descriptor.lifecycle.Phase;
31 import org.apache.maven.api.plugin.descriptor.lifecycle.Execution;
32 import org.codehaus.stax2.util.StreamWriterDelegate;
33
34 import static javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI;
35
36 @Generated
37 public class LifecycleStaxWriter {
38
39
40
41
42
43
44
45
46 private static final String NAMESPACE = "http://maven.apache.org/LIFECYCLE/2.0.0";
47
48
49
50
51 private static final String SCHEMA_LOCATION = "http://maven.apache.org/xsd/lifecycle-2.0.0.xsd";
52
53
54
55
56 private String namespace = NAMESPACE;
57
58
59
60
61 private String schemaLocation = SCHEMA_LOCATION;
62
63
64
65
66 private String fileComment = null;
67
68
69
70
71
72
73
74
75
76
77 public void setNamespace(String namespace) {
78 this.namespace = Objects.requireNonNull(namespace);
79 }
80
81
82
83
84
85
86 public void setSchemaLocation(String schemaLocation) {
87 this.schemaLocation = Objects.requireNonNull(schemaLocation);
88 }
89
90
91
92
93
94
95 public void setFileComment(String fileComment) {
96 this.fileComment = fileComment;
97 }
98
99
100
101
102
103
104
105
106 public void write(Writer writer, LifecycleConfiguration lifecycleConfiguration) throws IOException, XMLStreamException {
107 XMLOutputFactory factory = new com.ctc.wstx.stax.WstxOutputFactory();
108 factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false);
109 factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL, true);
110 factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM, true);
111 XMLStreamWriter serializer = new IndentingXMLStreamWriter(factory.createXMLStreamWriter(writer));
112 serializer.writeStartDocument(lifecycleConfiguration.getModelEncoding(), null);
113 writeLifecycleConfiguration("lifecycles", lifecycleConfiguration, serializer);
114 serializer.writeEndDocument();
115 }
116
117
118
119
120
121
122
123
124 public void write(OutputStream stream, LifecycleConfiguration lifecycleConfiguration) throws IOException, XMLStreamException {
125 XMLOutputFactory factory = new com.ctc.wstx.stax.WstxOutputFactory();
126 factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false);
127 factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL, true);
128 factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM, true);
129 XMLStreamWriter serializer = new IndentingXMLStreamWriter(factory.createXMLStreamWriter(stream, lifecycleConfiguration.getModelEncoding()));
130 serializer.writeStartDocument(lifecycleConfiguration.getModelEncoding(), null);
131 writeLifecycleConfiguration("lifecycles", lifecycleConfiguration, serializer);
132 serializer.writeEndDocument();
133 }
134
135 private void writeLifecycleConfiguration(String tagName, LifecycleConfiguration lifecycleConfiguration, XMLStreamWriter serializer)
136 throws IOException, XMLStreamException {
137 if (lifecycleConfiguration != null) {
138 if (this.fileComment != null) {
139 serializer.writeCharacters("\n");
140 serializer.writeComment(this.fileComment);
141 serializer.writeCharacters("\n");
142 }
143 serializer.writeStartElement("", tagName, namespace);
144 serializer.writeNamespace("", namespace);
145 serializer.writeNamespace("xsi", W3C_XML_SCHEMA_INSTANCE_NS_URI);
146 serializer.writeAttribute(W3C_XML_SCHEMA_INSTANCE_NS_URI, "schemaLocation", namespace + " " + schemaLocation);
147 writeList("lifecycles", true, lifecycleConfiguration.getLifecycles(), serializer,
148 t -> writeLifecycle("lifecycle", t, serializer));
149 serializer.writeEndElement();
150 }
151 }
152
153 private void writeLifecycle(String tagName, Lifecycle lifecycle, XMLStreamWriter serializer)
154 throws IOException, XMLStreamException {
155 if (lifecycle != null) {
156 serializer.writeStartElement(namespace, tagName);
157 writeTag("id", null, lifecycle.getId(), serializer);
158 writeList("phases", false, lifecycle.getPhases(), serializer,
159 t -> writePhase("phase", t, serializer));
160 serializer.writeEndElement();
161 }
162 }
163
164 private void writePhase(String tagName, Phase phase, XMLStreamWriter serializer)
165 throws IOException, XMLStreamException {
166 if (phase != null) {
167 serializer.writeStartElement(namespace, tagName);
168 writeAttr("executionPoint", phase.getExecutionPoint(), serializer);
169 writeAttr("priority", Integer.toString(phase.getPriority()), serializer);
170 writeTag("id", null, phase.getId(), serializer);
171 writeList("executions", false, phase.getExecutions(), serializer,
172 t -> writeExecution("execution", t, serializer));
173 writeDom(phase.getConfiguration(), serializer);
174 serializer.writeEndElement();
175 }
176 }
177
178 private void writeExecution(String tagName, Execution execution, XMLStreamWriter serializer)
179 throws IOException, XMLStreamException {
180 if (execution != null) {
181 serializer.writeStartElement(namespace, tagName);
182 writeDom(execution.getConfiguration(), serializer);
183 writeList("goals", execution.getGoals(), serializer,
184 t -> writeTag("goal", null, t, serializer));
185 serializer.writeEndElement();
186 }
187 }
188
189 @FunctionalInterface
190 private interface ElementWriter<T> {
191 public void write(T t) throws IOException, XMLStreamException;
192 }
193
194 private <T> void writeList(String tagName, List<T> list, XMLStreamWriter serializer, ElementWriter<T> writer) throws IOException, XMLStreamException {
195 writeList(tagName, false, list, serializer, writer);
196 }
197
198 private <T> void writeList(String tagName, boolean flat, List<T> list, XMLStreamWriter serializer, ElementWriter<T> writer) throws IOException, XMLStreamException {
199 if (list != null && !list.isEmpty()) {
200 if (!flat) {
201 serializer.writeStartElement(namespace, tagName);
202 }
203 int index = 0;
204 for (T t : list) {
205 writer.write(t);
206 }
207 if (!flat) {
208 serializer.writeEndElement();
209 }
210 }
211 }
212
213 private <T> void writeProperties(String tagName, Map<String, String> props, XMLStreamWriter serializer) throws IOException, XMLStreamException {
214 if (props != null && !props.isEmpty()) {
215 serializer.writeStartElement(namespace, tagName);
216 for (Map.Entry<String, String> entry : props.entrySet()) {
217 String key = entry.getKey();
218 writeTag(key, null, entry.getValue(), serializer);
219 }
220 serializer.writeEndElement();
221 }
222 }
223
224 private void writeDom(XmlNode dom, XMLStreamWriter serializer) throws IOException, XMLStreamException {
225 if (dom != null) {
226 serializer.writeStartElement(namespace, dom.getName());
227 for (Map.Entry<String, String> attr : dom.getAttributes().entrySet()) {
228 if (attr.getKey().startsWith("xml:")) {
229 serializer.writeAttribute("http://www.w3.org/XML/1998/namespace",
230 attr.getKey().substring(4), attr.getValue());
231 } else {
232 serializer.writeAttribute(attr.getKey(), attr.getValue());
233 }
234 }
235 for (XmlNode child : dom.getChildren()) {
236 writeDom(child, serializer);
237 }
238 String value = dom.getValue();
239 if (value != null) {
240 serializer.writeCharacters(value);
241 }
242 serializer.writeEndElement();
243 }
244 }
245
246 private void writeTag(String tagName, String defaultValue, String value, XMLStreamWriter serializer) throws IOException, XMLStreamException {
247 if (value != null && !Objects.equals(defaultValue, value)) {
248 serializer.writeStartElement(namespace, tagName);
249 serializer.writeCharacters(value);
250 serializer.writeEndElement();
251 }
252 }
253
254 private void writeAttr(String attrName, String value, XMLStreamWriter serializer) throws IOException, XMLStreamException {
255 if (value != null) {
256 serializer.writeAttribute(attrName, value);
257 }
258 }
259
260 static class IndentingXMLStreamWriter extends StreamWriterDelegate {
261
262 int depth = 0;
263 boolean hasChildren = false;
264
265 public IndentingXMLStreamWriter(XMLStreamWriter parent) {
266 super(parent);
267 }
268
269 @Override
270 public void writeEmptyElement(String localName) throws XMLStreamException {
271 indent();
272 super.writeEmptyElement(localName);
273 hasChildren = true;
274 }
275
276 @Override
277 public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
278 indent();
279 super.writeEmptyElement(namespaceURI, localName);
280 hasChildren = true;
281 }
282
283 @Override
284 public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
285 indent();
286 super.writeEmptyElement(prefix, localName, namespaceURI);
287 hasChildren = true;
288 }
289
290 @Override
291 public void writeStartElement(String localName) throws XMLStreamException {
292 indent();
293 super.writeStartElement(localName);
294 depth++;
295 hasChildren = false;
296 }
297
298 @Override
299 public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
300 indent();
301 super.writeStartElement(namespaceURI, localName);
302 depth++;
303 hasChildren = false;
304 }
305
306 @Override
307 public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
308 indent();
309 super.writeStartElement(prefix, localName, namespaceURI);
310 depth++;
311 hasChildren = false;
312 }
313
314 @Override
315 public void writeEndElement() throws XMLStreamException {
316 depth--;
317 if (hasChildren) {
318 indent();
319 }
320 super.writeEndElement();
321 hasChildren = true;
322 }
323
324 private void indent() throws XMLStreamException {
325 super.writeCharacters("\n");
326 for (int i = 0; i < depth; i++) {
327 super.writeCharacters(" ");
328 }
329 }
330 }
331 }