1
2
3
4
5 package org.apache.maven.artifact.repository.metadata.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.artifact.repository.metadata.v4.Metadata;
28 import org.apache.maven.artifact.repository.metadata.v4.Versioning;
29 import org.apache.maven.artifact.repository.metadata.v4.Snapshot;
30 import org.apache.maven.artifact.repository.metadata.v4.SnapshotVersion;
31 import org.apache.maven.artifact.repository.metadata.v4.Plugin;
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 MetadataStaxWriter {
38
39
40
41
42
43
44
45
46 private static final String NAMESPACE = "http://maven.apache.org/METADATA/1.1.0";
47
48
49
50
51 private static final String SCHEMA_LOCATION = "https://maven.apache.org/xsd/repository-metadata-1.1.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, Metadata metadata) 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(metadata.getModelEncoding(), null);
113 writeMetadata("metadata", metadata, serializer);
114 serializer.writeEndDocument();
115 }
116
117
118
119
120
121
122
123
124 public void write(OutputStream stream, Metadata metadata) 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, metadata.getModelEncoding()));
130 serializer.writeStartDocument(metadata.getModelEncoding(), null);
131 writeMetadata("metadata", metadata, serializer);
132 serializer.writeEndDocument();
133 }
134
135 private void writeMetadata(String tagName, Metadata metadata, XMLStreamWriter serializer)
136 throws IOException, XMLStreamException {
137 if (metadata != 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 writeAttr("modelVersion", metadata.getModelVersion(), serializer);
148 writeTag("groupId", null, metadata.getGroupId(), serializer);
149 writeTag("artifactId", null, metadata.getArtifactId(), serializer);
150 writeVersioning("versioning", metadata.getVersioning(), serializer);
151 writeTag("version", null, metadata.getVersion(), serializer);
152 writeList("plugins", false, metadata.getPlugins(), serializer,
153 t -> writePlugin("plugin", t, serializer));
154 serializer.writeEndElement();
155 }
156 }
157
158 private void writeVersioning(String tagName, Versioning versioning, XMLStreamWriter serializer)
159 throws IOException, XMLStreamException {
160 if (versioning != null) {
161 serializer.writeStartElement(namespace, tagName);
162 writeTag("latest", null, versioning.getLatest(), serializer);
163 writeTag("release", null, versioning.getRelease(), serializer);
164 writeList("versions", versioning.getVersions(), serializer,
165 t -> writeTag("version", null, t, serializer));
166 writeTag("lastUpdated", null, versioning.getLastUpdated(), serializer);
167 writeSnapshot("snapshot", versioning.getSnapshot(), serializer);
168 writeList("snapshotVersions", false, versioning.getSnapshotVersions(), serializer,
169 t -> writeSnapshotVersion("snapshotVersion", t, serializer));
170 serializer.writeEndElement();
171 }
172 }
173
174 private void writeSnapshot(String tagName, Snapshot snapshot, XMLStreamWriter serializer)
175 throws IOException, XMLStreamException {
176 if (snapshot != null) {
177 serializer.writeStartElement(namespace, tagName);
178 writeTag("timestamp", null, snapshot.getTimestamp(), serializer);
179 writeTag("buildNumber", "0", Integer.toString(snapshot.getBuildNumber()), serializer);
180 writeTag("localCopy", "false", snapshot.isLocalCopy() ? "true" : null, serializer);
181 serializer.writeEndElement();
182 }
183 }
184
185 private void writeSnapshotVersion(String tagName, SnapshotVersion snapshotVersion, XMLStreamWriter serializer)
186 throws IOException, XMLStreamException {
187 if (snapshotVersion != null) {
188 serializer.writeStartElement(namespace, tagName);
189 writeTag("classifier", null, snapshotVersion.getClassifier(), serializer);
190 writeTag("extension", null, snapshotVersion.getExtension(), serializer);
191 writeTag("value", null, snapshotVersion.getVersion(), serializer);
192 writeTag("updated", null, snapshotVersion.getUpdated(), serializer);
193 serializer.writeEndElement();
194 }
195 }
196
197 private void writePlugin(String tagName, Plugin plugin, XMLStreamWriter serializer)
198 throws IOException, XMLStreamException {
199 if (plugin != null) {
200 serializer.writeStartElement(namespace, tagName);
201 writeTag("name", null, plugin.getName(), serializer);
202 writeTag("prefix", null, plugin.getPrefix(), serializer);
203 writeTag("artifactId", null, plugin.getArtifactId(), serializer);
204 serializer.writeEndElement();
205 }
206 }
207
208 @FunctionalInterface
209 private interface ElementWriter<T> {
210 public void write(T t) throws IOException, XMLStreamException;
211 }
212
213 private <T> void writeList(String tagName, List<T> list, XMLStreamWriter serializer, ElementWriter<T> writer) throws IOException, XMLStreamException {
214 writeList(tagName, false, list, serializer, writer);
215 }
216
217 private <T> void writeList(String tagName, boolean flat, List<T> list, XMLStreamWriter serializer, ElementWriter<T> writer) throws IOException, XMLStreamException {
218 if (list != null && !list.isEmpty()) {
219 if (!flat) {
220 serializer.writeStartElement(namespace, tagName);
221 }
222 int index = 0;
223 for (T t : list) {
224 writer.write(t);
225 }
226 if (!flat) {
227 serializer.writeEndElement();
228 }
229 }
230 }
231
232 private <T> void writeProperties(String tagName, Map<String, String> props, XMLStreamWriter serializer) throws IOException, XMLStreamException {
233 if (props != null && !props.isEmpty()) {
234 serializer.writeStartElement(namespace, tagName);
235 for (Map.Entry<String, String> entry : props.entrySet()) {
236 String key = entry.getKey();
237 writeTag(key, null, entry.getValue(), serializer);
238 }
239 serializer.writeEndElement();
240 }
241 }
242
243 private void writeDom(XmlNode dom, XMLStreamWriter serializer) throws IOException, XMLStreamException {
244 if (dom != null) {
245 serializer.writeStartElement(namespace, dom.getName());
246 for (Map.Entry<String, String> attr : dom.getAttributes().entrySet()) {
247 if (attr.getKey().startsWith("xml:")) {
248 serializer.writeAttribute("http://www.w3.org/XML/1998/namespace",
249 attr.getKey().substring(4), attr.getValue());
250 } else {
251 serializer.writeAttribute(attr.getKey(), attr.getValue());
252 }
253 }
254 for (XmlNode child : dom.getChildren()) {
255 writeDom(child, serializer);
256 }
257 String value = dom.getValue();
258 if (value != null) {
259 serializer.writeCharacters(value);
260 }
261 serializer.writeEndElement();
262 }
263 }
264
265 private void writeTag(String tagName, String defaultValue, String value, XMLStreamWriter serializer) throws IOException, XMLStreamException {
266 if (value != null && !Objects.equals(defaultValue, value)) {
267 serializer.writeStartElement(namespace, tagName);
268 serializer.writeCharacters(value);
269 serializer.writeEndElement();
270 }
271 }
272
273 private void writeAttr(String attrName, String value, XMLStreamWriter serializer) throws IOException, XMLStreamException {
274 if (value != null) {
275 serializer.writeAttribute(attrName, value);
276 }
277 }
278
279 static class IndentingXMLStreamWriter extends StreamWriterDelegate {
280
281 int depth = 0;
282 boolean hasChildren = false;
283
284 public IndentingXMLStreamWriter(XMLStreamWriter parent) {
285 super(parent);
286 }
287
288 @Override
289 public void writeEmptyElement(String localName) throws XMLStreamException {
290 indent();
291 super.writeEmptyElement(localName);
292 hasChildren = true;
293 }
294
295 @Override
296 public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
297 indent();
298 super.writeEmptyElement(namespaceURI, localName);
299 hasChildren = true;
300 }
301
302 @Override
303 public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
304 indent();
305 super.writeEmptyElement(prefix, localName, namespaceURI);
306 hasChildren = true;
307 }
308
309 @Override
310 public void writeStartElement(String localName) throws XMLStreamException {
311 indent();
312 super.writeStartElement(localName);
313 depth++;
314 hasChildren = false;
315 }
316
317 @Override
318 public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
319 indent();
320 super.writeStartElement(namespaceURI, localName);
321 depth++;
322 hasChildren = false;
323 }
324
325 @Override
326 public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
327 indent();
328 super.writeStartElement(prefix, localName, namespaceURI);
329 depth++;
330 hasChildren = false;
331 }
332
333 @Override
334 public void writeEndElement() throws XMLStreamException {
335 depth--;
336 if (hasChildren) {
337 indent();
338 }
339 super.writeEndElement();
340 hasChildren = true;
341 }
342
343 private void indent() throws XMLStreamException {
344 super.writeCharacters("\n");
345 for (int i = 0; i < depth; i++) {
346 super.writeCharacters(" ");
347 }
348 }
349 }
350 }