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