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