View Javadoc
1   // =================== DO NOT EDIT THIS FILE ====================
2   //  Generated by Modello Velocity from reader-stax.vm
3   //  template, any modifications will be overwritten.
4   // ==============================================================
5   package org.apache.maven.plugin.descriptor.io;
6   
7   import java.io.IOException;
8   import java.io.InputStream;
9   import java.io.Reader;
10  import java.text.DateFormat;
11  import java.util.ArrayDeque;
12  import java.util.ArrayList;
13  import java.util.Collections;
14  import java.util.Date;
15  import java.util.Deque;
16  import java.util.HashMap;
17  import java.util.HashSet;
18  import java.util.LinkedHashMap;
19  import java.util.List;
20  import java.util.Map;
21  import java.util.Set;
22  import org.apache.maven.api.annotations.Generated;
23  import org.apache.maven.api.plugin.descriptor.PluginDescriptor;
24  import org.apache.maven.api.plugin.descriptor.MojoDescriptor;
25  import org.apache.maven.api.plugin.descriptor.Parameter;
26  import org.apache.maven.api.plugin.descriptor.Requirement;
27  import org.apache.maven.api.plugin.descriptor.Dependency;
28  import org.apache.maven.internal.xml.XmlNodeBuilder;
29  import org.apache.maven.api.xml.XmlNode;
30  import javax.xml.stream.XMLInputFactory;
31  import javax.xml.stream.XMLStreamException;
32  import javax.xml.stream.XMLStreamReader;
33  import javax.xml.transform.stream.StreamSource;
34  
35  import static javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI;
36  import static javax.xml.XMLConstants.XML_NS_URI;
37  
38  @Generated
39  public class PluginDescriptorStaxReader {
40  
41      private static final Map<String, String> DEFAULT_ENTITIES;
42      static {
43          Map<String, String> entities = new HashMap<>();
44          entities.put("nbsp", "\u00a0");
45          entities.put("iexcl", "\u00a1");
46          entities.put("cent", "\u00a2");
47          entities.put("pound", "\u00a3");
48          entities.put("curren", "\u00a4");
49          entities.put("yen", "\u00a5");
50          entities.put("brvbar", "\u00a6");
51          entities.put("sect", "\u00a7");
52          entities.put("uml", "\u00a8");
53          entities.put("copy", "\u00a9");
54          entities.put("ordf", "\u00aa");
55          entities.put("laquo", "\u00ab");
56          entities.put("not", "\u00ac");
57          entities.put("shy", "\u00ad");
58          entities.put("reg", "\u00ae");
59          entities.put("macr", "\u00af");
60          entities.put("deg", "\u00b0");
61          entities.put("plusmn", "\u00b1");
62          entities.put("sup2", "\u00b2");
63          entities.put("sup3", "\u00b3");
64          entities.put("acute", "\u00b4");
65          entities.put("micro", "\u00b5");
66          entities.put("para", "\u00b6");
67          entities.put("middot", "\u00b7");
68          entities.put("cedil", "\u00b8");
69          entities.put("sup1", "\u00b9");
70          entities.put("ordm", "\u00ba");
71          entities.put("raquo", "\u00bb");
72          entities.put("frac14", "\u00bc");
73          entities.put("frac12", "\u00bd");
74          entities.put("frac34", "\u00be");
75          entities.put("iquest", "\u00bf");
76          entities.put("Agrave", "\u00c0");
77          entities.put("Aacute", "\u00c1");
78          entities.put("Acirc", "\u00c2");
79          entities.put("Atilde", "\u00c3");
80          entities.put("Auml", "\u00c4");
81          entities.put("Aring", "\u00c5");
82          entities.put("AElig", "\u00c6");
83          entities.put("Ccedil", "\u00c7");
84          entities.put("Egrave", "\u00c8");
85          entities.put("Eacute", "\u00c9");
86          entities.put("Ecirc", "\u00ca");
87          entities.put("Euml", "\u00cb");
88          entities.put("Igrave", "\u00cc");
89          entities.put("Iacute", "\u00cd");
90          entities.put("Icirc", "\u00ce");
91          entities.put("Iuml", "\u00cf");
92          entities.put("ETH", "\u00d0");
93          entities.put("Ntilde", "\u00d1");
94          entities.put("Ograve", "\u00d2");
95          entities.put("Oacute", "\u00d3");
96          entities.put("Ocirc", "\u00d4");
97          entities.put("Otilde", "\u00d5");
98          entities.put("Ouml", "\u00d6");
99          entities.put("times", "\u00d7");
100         entities.put("Oslash", "\u00d8");
101         entities.put("Ugrave", "\u00d9");
102         entities.put("Uacute", "\u00da");
103         entities.put("Ucirc", "\u00db");
104         entities.put("Uuml", "\u00dc");
105         entities.put("Yacute", "\u00dd");
106         entities.put("THORN", "\u00de");
107         entities.put("szlig", "\u00df");
108         entities.put("agrave", "\u00e0");
109         entities.put("aacute", "\u00e1");
110         entities.put("acirc", "\u00e2");
111         entities.put("atilde", "\u00e3");
112         entities.put("auml", "\u00e4");
113         entities.put("aring", "\u00e5");
114         entities.put("aelig", "\u00e6");
115         entities.put("ccedil", "\u00e7");
116         entities.put("egrave", "\u00e8");
117         entities.put("eacute", "\u00e9");
118         entities.put("ecirc", "\u00ea");
119         entities.put("euml", "\u00eb");
120         entities.put("igrave", "\u00ec");
121         entities.put("iacute", "\u00ed");
122         entities.put("icirc", "\u00ee");
123         entities.put("iuml", "\u00ef");
124         entities.put("eth", "\u00f0");
125         entities.put("ntilde", "\u00f1");
126         entities.put("ograve", "\u00f2");
127         entities.put("oacute", "\u00f3");
128         entities.put("ocirc", "\u00f4");
129         entities.put("otilde", "\u00f5");
130         entities.put("ouml", "\u00f6");
131         entities.put("divide", "\u00f7");
132         entities.put("oslash", "\u00f8");
133         entities.put("ugrave", "\u00f9");
134         entities.put("uacute", "\u00fa");
135         entities.put("ucirc", "\u00fb");
136         entities.put("uuml", "\u00fc");
137         entities.put("yacute", "\u00fd");
138         entities.put("thorn", "\u00fe");
139         entities.put("yuml", "\u00ff");
140 
141         // ----------------------------------------------------------------------
142         // Special entities
143         // ----------------------------------------------------------------------
144 
145         entities.put("OElig", "\u0152");
146         entities.put("oelig", "\u0153");
147         entities.put("Scaron", "\u0160");
148         entities.put("scaron", "\u0161");
149         entities.put("Yuml", "\u0178");
150         entities.put("circ", "\u02c6");
151         entities.put("tilde", "\u02dc");
152         entities.put("ensp", "\u2002");
153         entities.put("emsp", "\u2003");
154         entities.put("thinsp", "\u2009");
155         entities.put("zwnj", "\u200c");
156         entities.put("zwj", "\u200d");
157         entities.put("lrm", "\u200e");
158         entities.put("rlm", "\u200f");
159         entities.put("ndash", "\u2013");
160         entities.put("mdash", "\u2014");
161         entities.put("lsquo", "\u2018");
162         entities.put("rsquo", "\u2019");
163         entities.put("sbquo", "\u201a");
164         entities.put("ldquo", "\u201c");
165         entities.put("rdquo", "\u201d");
166         entities.put("bdquo", "\u201e");
167         entities.put("dagger", "\u2020");
168         entities.put("Dagger", "\u2021");
169         entities.put("permil", "\u2030");
170         entities.put("lsaquo", "\u2039");
171         entities.put("rsaquo", "\u203a");
172         entities.put("euro", "\u20ac");
173 
174         // ----------------------------------------------------------------------
175         // Symbol entities
176         // ----------------------------------------------------------------------
177 
178         entities.put("fnof", "\u0192");
179         entities.put("Alpha", "\u0391");
180         entities.put("Beta", "\u0392");
181         entities.put("Gamma", "\u0393");
182         entities.put("Delta", "\u0394");
183         entities.put("Epsilon", "\u0395");
184         entities.put("Zeta", "\u0396");
185         entities.put("Eta", "\u0397");
186         entities.put("Theta", "\u0398");
187         entities.put("Iota", "\u0399");
188         entities.put("Kappa", "\u039a");
189         entities.put("Lambda", "\u039b");
190         entities.put("Mu", "\u039c");
191         entities.put("Nu", "\u039d");
192         entities.put("Xi", "\u039e");
193         entities.put("Omicron", "\u039f");
194         entities.put("Pi", "\u03a0");
195         entities.put("Rho", "\u03a1");
196         entities.put("Sigma", "\u03a3");
197         entities.put("Tau", "\u03a4");
198         entities.put("Upsilon", "\u03a5");
199         entities.put("Phi", "\u03a6");
200         entities.put("Chi", "\u03a7");
201         entities.put("Psi", "\u03a8");
202         entities.put("Omega", "\u03a9");
203         entities.put("alpha", "\u03b1");
204         entities.put("beta", "\u03b2");
205         entities.put("gamma", "\u03b3");
206         entities.put("delta", "\u03b4");
207         entities.put("epsilon", "\u03b5");
208         entities.put("zeta", "\u03b6");
209         entities.put("eta", "\u03b7");
210         entities.put("theta", "\u03b8");
211         entities.put("iota", "\u03b9");
212         entities.put("kappa", "\u03ba");
213         entities.put("lambda", "\u03bb");
214         entities.put("mu", "\u03bc");
215         entities.put("nu", "\u03bd");
216         entities.put("xi", "\u03be");
217         entities.put("omicron", "\u03bf");
218         entities.put("pi", "\u03c0");
219         entities.put("rho", "\u03c1");
220         entities.put("sigmaf", "\u03c2");
221         entities.put("sigma", "\u03c3");
222         entities.put("tau", "\u03c4");
223         entities.put("upsilon", "\u03c5");
224         entities.put("phi", "\u03c6");
225         entities.put("chi", "\u03c7");
226         entities.put("psi", "\u03c8");
227         entities.put("omega", "\u03c9");
228         entities.put("thetasym", "\u03d1");
229         entities.put("upsih", "\u03d2");
230         entities.put("piv", "\u03d6");
231         entities.put("bull", "\u2022");
232         entities.put("hellip", "\u2026");
233         entities.put("prime", "\u2032");
234         entities.put("Prime", "\u2033");
235         entities.put("oline", "\u203e");
236         entities.put("frasl", "\u2044");
237         entities.put("weierp", "\u2118");
238         entities.put("image", "\u2111");
239         entities.put("real", "\u211c");
240         entities.put("trade", "\u2122");
241         entities.put("alefsym", "\u2135");
242         entities.put("larr", "\u2190");
243         entities.put("uarr", "\u2191");
244         entities.put("rarr", "\u2192");
245         entities.put("darr", "\u2193");
246         entities.put("harr", "\u2194");
247         entities.put("crarr", "\u21b5");
248         entities.put("lArr", "\u21d0");
249         entities.put("uArr", "\u21d1");
250         entities.put("rArr", "\u21d2");
251         entities.put("dArr", "\u21d3");
252         entities.put("hArr", "\u21d4");
253         entities.put("forall", "\u2200");
254         entities.put("part", "\u2202");
255         entities.put("exist", "\u2203");
256         entities.put("empty", "\u2205");
257         entities.put("nabla", "\u2207");
258         entities.put("isin", "\u2208");
259         entities.put("notin", "\u2209");
260         entities.put("ni", "\u220b");
261         entities.put("prod", "\u220f");
262         entities.put("sum", "\u2211");
263         entities.put("minus", "\u2212");
264         entities.put("lowast", "\u2217");
265         entities.put("radic", "\u221a");
266         entities.put("prop", "\u221d");
267         entities.put("infin", "\u221e");
268         entities.put("ang", "\u2220");
269         entities.put("and", "\u2227");
270         entities.put("or", "\u2228");
271         entities.put("cap", "\u2229");
272         entities.put("cup", "\u222a");
273         entities.put("int", "\u222b");
274         entities.put("there4", "\u2234");
275         entities.put("sim", "\u223c");
276         entities.put("cong", "\u2245");
277         entities.put("asymp", "\u2248");
278         entities.put("ne", "\u2260");
279         entities.put("equiv", "\u2261");
280         entities.put("le", "\u2264");
281         entities.put("ge", "\u2265");
282         entities.put("sub", "\u2282");
283         entities.put("sup", "\u2283");
284         entities.put("nsub", "\u2284");
285         entities.put("sube", "\u2286");
286         entities.put("supe", "\u2287");
287         entities.put("oplus", "\u2295");
288         entities.put("otimes", "\u2297");
289         entities.put("perp", "\u22a5");
290         entities.put("sdot", "\u22c5");
291         entities.put("lceil", "\u2308");
292         entities.put("rceil", "\u2309");
293         entities.put("lfloor", "\u230a");
294         entities.put("rfloor", "\u230b");
295         entities.put("lang", "\u2329");
296         entities.put("rang", "\u232a");
297         entities.put("loz", "\u25ca");
298         entities.put("spades", "\u2660");
299         entities.put("clubs", "\u2663");
300         entities.put("hearts", "\u2665");
301         entities.put("diams", "\u2666");
302         DEFAULT_ENTITIES = Collections.unmodifiableMap(entities);
303     }
304 
305     private boolean addDefaultEntities = true;
306 
307     private final ContentTransformer contentTransformer;
308 
309     public PluginDescriptorStaxReader() {
310         this((s, f) -> s);
311     }
312 
313     public PluginDescriptorStaxReader(ContentTransformer contentTransformer) {
314         this.contentTransformer = contentTransformer;
315     }
316 
317     /**
318      * Returns the state of the "add default entities" flag.
319      *
320      * @return boolean
321      */
322     public boolean getAddDefaultEntities() {
323         return addDefaultEntities;
324     } //-- boolean getAddDefaultEntities()
325 
326     /**
327      * Sets the state of the "add default entities" flag.
328      *
329      * @param addDefaultEntities a addDefaultEntities object.
330      */
331     public void setAddDefaultEntities(boolean addDefaultEntities) {
332         this.addDefaultEntities = addDefaultEntities;
333     } //-- void setAddDefaultEntities(boolean)
334 
335 
336     public PluginDescriptor read(Reader reader) throws XMLStreamException {
337         return read(reader, true);
338     }
339 
340     /**
341      * @param reader a reader object.
342      * @param strict a strict object.
343      * @throws XMLStreamException XMLStreamException if
344      * any.
345      * @return PluginDescriptor
346      */
347     public PluginDescriptor read(Reader reader, boolean strict) throws XMLStreamException {
348         XMLInputFactory factory = new com.ctc.wstx.stax.WstxInputFactory();
349         factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
350         StreamSource streamSource = new StreamSource(reader);
351         XMLStreamReader parser = factory.createXMLStreamReader(streamSource);
352     return read(parser, strict);
353     } //-- PluginDescriptor read(Reader, boolean)
354 
355     public PluginDescriptor read(InputStream in) throws XMLStreamException {
356         return read(in, true);
357     }
358 
359     /**
360      * Method read.
361      *
362      * @param in a in object.
363      * @param strict a strict object.
364      * @throws XMLStreamException XMLStreamException if
365      * any.
366      * @return PluginDescriptor
367      */
368     public PluginDescriptor read(InputStream in, boolean strict) throws XMLStreamException {
369         XMLInputFactory factory = new com.ctc.wstx.stax.WstxInputFactory();
370         factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
371         StreamSource streamSource = new StreamSource(in);
372         XMLStreamReader parser = factory.createXMLStreamReader(streamSource);
373         return read(parser, strict);
374     } //-- PluginDescriptor read(InputStream, boolean)
375 
376     /**
377      * Method read.
378      *
379      * @param parser a parser object.
380      * @param strict a strict object.
381      * @throws XMLStreamException XMLStreamException if
382      * any.
383      * @return PluginDescriptor
384      */
385     public PluginDescriptor read(XMLStreamReader parser, boolean strict) throws XMLStreamException {
386         Deque<Object> context = new ArrayDeque<>();
387         PluginDescriptor pluginDescriptor = null;
388         int eventType = parser.getEventType();
389         boolean parsed = false;
390         while (eventType != XMLStreamReader.END_DOCUMENT) {
391             if (eventType == XMLStreamReader.START_ELEMENT) {
392                 if (strict && ! "plugin".equals(parser.getLocalName())) {
393                     throw new XMLStreamException("Expected root element 'plugin' but found '" + parser.getName() + "'", parser.getLocation(), null);
394                 } else if (parsed) {
395                     // fallback, already expected a XMLStreamException due to invalid XML
396                     throw new XMLStreamException("Duplicated tag: 'plugin'", parser.getLocation(), null);
397                 }
398                 pluginDescriptor = parsePluginDescriptor(parser, strict, context);
399                 parsed = true;
400             }
401             eventType = parser.next();
402         }
403         if (parsed) {
404             return pluginDescriptor;
405         }
406         throw new XMLStreamException("Expected root element 'plugin' but found no element at all: invalid XML document", parser.getLocation(), null);
407     } //-- PluginDescriptor read(XMLStreamReader, boolean)
408 
409     private PluginDescriptor parsePluginDescriptor(XMLStreamReader parser, boolean strict, Deque<Object> context) throws XMLStreamException {
410         String tagName = parser.getLocalName();
411         PluginDescriptor.Builder pluginDescriptor = PluginDescriptor.newBuilder(true);
412         for (int i = parser.getAttributeCount() - 1; i >= 0; i--) {
413             String name = parser.getAttributeLocalName(i);
414             String ns = parser.getAttributeNamespace(i);
415             String value = parser.getAttributeValue(i);
416             if (W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(ns) || XML_NS_URI.equals(ns)) {
417                 // just ignore attributes with non-default namespace (for example: xsi and xml)
418             } else if ("xmlns".equals(name)) {
419                 // ignore xmlns attribute in root class, which is a reserved attribute name
420             } else {
421                 checkUnknownAttribute(parser, name, tagName, strict);
422             }
423         }
424         Set<String> parsed = new HashSet<>();
425         context.addLast( pluginDescriptor );
426         while ((strict ? parser.nextTag() : nextTag(parser)) == XMLStreamReader.START_ELEMENT) {
427             String childName = checkDuplicate(parser.getLocalName(), parser, parsed);
428             switch (childName) {
429                 case "name": {
430                     pluginDescriptor.name(interpolatedTrimmed(nextText(parser, strict), "name"));
431                     break;
432                 }
433                 case "description": {
434                     pluginDescriptor.description(interpolatedTrimmed(nextText(parser, strict), "description"));
435                     break;
436                 }
437                 case "groupId": {
438                     pluginDescriptor.groupId(interpolatedTrimmed(nextText(parser, strict), "groupId"));
439                     break;
440                 }
441                 case "artifactId": {
442                     pluginDescriptor.artifactId(interpolatedTrimmed(nextText(parser, strict), "artifactId"));
443                     break;
444                 }
445                 case "version": {
446                     pluginDescriptor.version(interpolatedTrimmed(nextText(parser, strict), "version"));
447                     break;
448                 }
449                 case "goalPrefix": {
450                     pluginDescriptor.goalPrefix(interpolatedTrimmed(nextText(parser, strict), "goalPrefix"));
451                     break;
452                 }
453                 case "isolatedRealm": {
454                     pluginDescriptor.isolatedRealm(getBooleanValue(interpolatedTrimmed(nextText(parser, strict), "isolatedRealm"), "isolatedRealm", parser, false));
455                     break;
456                 }
457                 case "inheritedByDefault": {
458                     pluginDescriptor.inheritedByDefault(getBooleanValue(interpolatedTrimmed(nextText(parser, strict), "inheritedByDefault"), "inheritedByDefault", parser, true));
459                     break;
460                 }
461                 case "requiredJavaVersion": {
462                     pluginDescriptor.requiredJavaVersion(interpolatedTrimmed(nextText(parser, strict), "requiredJavaVersion"));
463                     break;
464                 }
465                 case "requiredMavenVersion": {
466                     pluginDescriptor.requiredMavenVersion(interpolatedTrimmed(nextText(parser, strict), "requiredMavenVersion"));
467                     break;
468                 }
469                 case "mojos": {
470                     List<MojoDescriptor> mojos = new ArrayList<>();
471                     while (parser.nextTag() == XMLStreamReader.START_ELEMENT) {
472                         if ("mojo".equals(parser.getLocalName())) {
473                             mojos.add(parseMojoDescriptor(parser, strict, context));
474                         } else {
475                             checkUnknownElement(parser, strict);
476                         }
477                     }
478                     pluginDescriptor.mojos(mojos);
479                     break;
480                 }
481                 default: {
482                     checkUnknownElement(parser, strict);
483                     break;
484                 }
485             }
486         }
487         context.removeLast();
488         pluginDescriptor.namespaceUri(parser.getNamespaceURI());
489         pluginDescriptor.modelEncoding(parser.getEncoding());
490         return pluginDescriptor.build();
491     }
492 
493     private MojoDescriptor parseMojoDescriptor(XMLStreamReader parser, boolean strict, Deque<Object> context) throws XMLStreamException {
494         String tagName = parser.getLocalName();
495         MojoDescriptor.Builder mojoDescriptor = MojoDescriptor.newBuilder(true);
496         for (int i = parser.getAttributeCount() - 1; i >= 0; i--) {
497             String name = parser.getAttributeLocalName(i);
498             String ns = parser.getAttributeNamespace(i);
499             String value = parser.getAttributeValue(i);
500             if (W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(ns) || XML_NS_URI.equals(ns)) {
501                 // just ignore attributes with non-default namespace (for example: xsi and xml)
502             } else {
503                 checkUnknownAttribute(parser, name, tagName, strict);
504             }
505         }
506         Set<String> parsed = new HashSet<>();
507         context.addLast( mojoDescriptor );
508         while ((strict ? parser.nextTag() : nextTag(parser)) == XMLStreamReader.START_ELEMENT) {
509             String childName = checkDuplicate(parser.getLocalName(), parser, parsed);
510             switch (childName) {
511                 case "goal": {
512                     mojoDescriptor.goal(interpolatedTrimmed(nextText(parser, strict), "goal"));
513                     break;
514                 }
515                 case "description": {
516                     mojoDescriptor.description(interpolatedTrimmed(nextText(parser, strict), "description"));
517                     break;
518                 }
519                 case "implementation": {
520                     mojoDescriptor.implementation(interpolatedTrimmed(nextText(parser, strict), "implementation"));
521                     break;
522                 }
523                 case "language": {
524                     mojoDescriptor.language(interpolatedTrimmed(nextText(parser, strict), "language"));
525                     break;
526                 }
527                 case "phase": {
528                     mojoDescriptor.phase(interpolatedTrimmed(nextText(parser, strict), "phase"));
529                     break;
530                 }
531                 case "executePhase": {
532                     mojoDescriptor.executePhase(interpolatedTrimmed(nextText(parser, strict), "executePhase"));
533                     break;
534                 }
535                 case "executeGoal": {
536                     mojoDescriptor.executeGoal(interpolatedTrimmed(nextText(parser, strict), "executeGoal"));
537                     break;
538                 }
539                 case "executeLifecycle": {
540                     mojoDescriptor.executeLifecycle(interpolatedTrimmed(nextText(parser, strict), "executeLifecycle"));
541                     break;
542                 }
543                 case "dependencyResolution": {
544                     mojoDescriptor.dependencyResolution(interpolatedTrimmed(nextText(parser, strict), "dependencyResolution"));
545                     break;
546                 }
547                 case "dependencyCollection": {
548                     mojoDescriptor.dependencyCollection(interpolatedTrimmed(nextText(parser, strict), "dependencyCollection"));
549                     break;
550                 }
551                 case "directInvocationOnly": {
552                     mojoDescriptor.directInvocationOnly(getBooleanValue(interpolatedTrimmed(nextText(parser, strict), "directInvocationOnly"), "directInvocationOnly", parser, false));
553                     break;
554                 }
555                 case "projectRequired": {
556                     mojoDescriptor.projectRequired(getBooleanValue(interpolatedTrimmed(nextText(parser, strict), "projectRequired"), "projectRequired", parser, true));
557                     break;
558                 }
559                 case "onlineRequired": {
560                     mojoDescriptor.onlineRequired(getBooleanValue(interpolatedTrimmed(nextText(parser, strict), "onlineRequired"), "onlineRequired", parser, false));
561                     break;
562                 }
563                 case "aggregator": {
564                     mojoDescriptor.aggregator(getBooleanValue(interpolatedTrimmed(nextText(parser, strict), "aggregator"), "aggregator", parser, false));
565                     break;
566                 }
567                 case "inheritedByDefault": {
568                     mojoDescriptor.inheritedByDefault(getBooleanValue(interpolatedTrimmed(nextText(parser, strict), "inheritedByDefault"), "inheritedByDefault", parser, true));
569                     break;
570                 }
571                 case "since": {
572                     mojoDescriptor.since(interpolatedTrimmed(nextText(parser, strict), "since"));
573                     break;
574                 }
575                 case "deprecated": {
576                     mojoDescriptor.deprecated(interpolatedTrimmed(nextText(parser, strict), "deprecated"));
577                     break;
578                 }
579                 case "configurator": {
580                     mojoDescriptor.configurator(interpolatedTrimmed(nextText(parser, strict), "configurator"));
581                     break;
582                 }
583                 case "parameters": {
584                     List<Parameter> parameters = new ArrayList<>();
585                     while (parser.nextTag() == XMLStreamReader.START_ELEMENT) {
586                         if ("parameter".equals(parser.getLocalName())) {
587                             parameters.add(parseParameter(parser, strict, context));
588                         } else {
589                             checkUnknownElement(parser, strict);
590                         }
591                     }
592                     mojoDescriptor.parameters(parameters);
593                     break;
594                 }
595                 default: {
596                     checkUnknownElement(parser, strict);
597                     break;
598                 }
599             }
600         }
601         context.removeLast();
602         mojoDescriptor.id(((PluginDescriptor.Builder) context.peekLast()).build().getId() + ":" + mojoDescriptor.build().getGoal());
603         mojoDescriptor.fullGoalName(((PluginDescriptor.Builder) context.peekLast()).build().getGoalPrefix() + ":" + mojoDescriptor.build().getGoal());
604         return mojoDescriptor.build();
605     }
606 
607     private Parameter parseParameter(XMLStreamReader parser, boolean strict, Deque<Object> context) throws XMLStreamException {
608         String tagName = parser.getLocalName();
609         Parameter.Builder parameter = Parameter.newBuilder(true);
610         for (int i = parser.getAttributeCount() - 1; i >= 0; i--) {
611             String name = parser.getAttributeLocalName(i);
612             String ns = parser.getAttributeNamespace(i);
613             String value = parser.getAttributeValue(i);
614             if (W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(ns) || XML_NS_URI.equals(ns)) {
615                 // just ignore attributes with non-default namespace (for example: xsi and xml)
616             } else {
617                 checkUnknownAttribute(parser, name, tagName, strict);
618             }
619         }
620         Set<String> parsed = new HashSet<>();
621         context.addLast( parameter );
622         while ((strict ? parser.nextTag() : nextTag(parser)) == XMLStreamReader.START_ELEMENT) {
623             String childName = checkDuplicate(parser.getLocalName(), parser, parsed);
624             switch (childName) {
625                 case "name": {
626                     parameter.name(interpolatedTrimmed(nextText(parser, strict), "name"));
627                     break;
628                 }
629                 case "alias": {
630                     parameter.alias(interpolatedTrimmed(nextText(parser, strict), "alias"));
631                     break;
632                 }
633                 case "type": {
634                     parameter.type(interpolatedTrimmed(nextText(parser, strict), "type"));
635                     break;
636                 }
637                 case "required": {
638                     parameter.required(getBooleanValue(interpolatedTrimmed(nextText(parser, strict), "required"), "required", parser, false));
639                     break;
640                 }
641                 case "editable": {
642                     parameter.editable(getBooleanValue(interpolatedTrimmed(nextText(parser, strict), "editable"), "editable", parser, true));
643                     break;
644                 }
645                 case "description": {
646                     parameter.description(interpolatedTrimmed(nextText(parser, strict), "description"));
647                     break;
648                 }
649                 case "since": {
650                     parameter.since(interpolatedTrimmed(nextText(parser, strict), "since"));
651                     break;
652                 }
653                 case "deprecated": {
654                     parameter.deprecated(interpolatedTrimmed(nextText(parser, strict), "deprecated"));
655                     break;
656                 }
657                 case "expression": {
658                     parameter.expression(interpolatedTrimmed(nextText(parser, strict), "expression"));
659                     break;
660                 }
661                 case "defaultValue": {
662                     parameter.defaultValue(interpolatedTrimmed(nextText(parser, strict), "defaultValue"));
663                     break;
664                 }
665                 default: {
666                     checkUnknownElement(parser, strict);
667                     break;
668                 }
669             }
670         }
671         context.removeLast();
672         return parameter.build();
673     }
674 
675     private Requirement parseRequirement(XMLStreamReader parser, boolean strict, Deque<Object> context) throws XMLStreamException {
676         String tagName = parser.getLocalName();
677         Requirement.Builder requirement = Requirement.newBuilder(true);
678         for (int i = parser.getAttributeCount() - 1; i >= 0; i--) {
679             String name = parser.getAttributeLocalName(i);
680             String ns = parser.getAttributeNamespace(i);
681             String value = parser.getAttributeValue(i);
682             if (W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(ns) || XML_NS_URI.equals(ns)) {
683                 // just ignore attributes with non-default namespace (for example: xsi and xml)
684             } else {
685                 checkUnknownAttribute(parser, name, tagName, strict);
686             }
687         }
688         Set<String> parsed = new HashSet<>();
689         context.addLast( requirement );
690         while ((strict ? parser.nextTag() : nextTag(parser)) == XMLStreamReader.START_ELEMENT) {
691             String childName = checkDuplicate(parser.getLocalName(), parser, parsed);
692             switch (childName) {
693                 case "role": {
694                     requirement.role(interpolatedTrimmed(nextText(parser, strict), "role"));
695                     break;
696                 }
697                 case "role-hint": {
698                     requirement.roleHint(interpolatedTrimmed(nextText(parser, strict), "role-hint"));
699                     break;
700                 }
701                 case "field-name": {
702                     requirement.fieldName(interpolatedTrimmed(nextText(parser, strict), "field-name"));
703                     break;
704                 }
705                 default: {
706                     checkUnknownElement(parser, strict);
707                     break;
708                 }
709             }
710         }
711         context.removeLast();
712         return requirement.build();
713     }
714 
715     private Dependency parseDependency(XMLStreamReader parser, boolean strict, Deque<Object> context) throws XMLStreamException {
716         String tagName = parser.getLocalName();
717         Dependency.Builder dependency = Dependency.newBuilder(true);
718         for (int i = parser.getAttributeCount() - 1; i >= 0; i--) {
719             String name = parser.getAttributeLocalName(i);
720             String ns = parser.getAttributeNamespace(i);
721             String value = parser.getAttributeValue(i);
722             if (W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(ns) || XML_NS_URI.equals(ns)) {
723                 // just ignore attributes with non-default namespace (for example: xsi and xml)
724             } else {
725                 checkUnknownAttribute(parser, name, tagName, strict);
726             }
727         }
728         Set<String> parsed = new HashSet<>();
729         context.addLast( dependency );
730         while ((strict ? parser.nextTag() : nextTag(parser)) == XMLStreamReader.START_ELEMENT) {
731             String childName = checkDuplicate(parser.getLocalName(), parser, parsed);
732             switch (childName) {
733                 case "groupId": {
734                     dependency.groupId(interpolatedTrimmed(nextText(parser, strict), "groupId"));
735                     break;
736                 }
737                 case "artifactId": {
738                     dependency.artifactId(interpolatedTrimmed(nextText(parser, strict), "artifactId"));
739                     break;
740                 }
741                 case "version": {
742                     dependency.version(interpolatedTrimmed(nextText(parser, strict), "version"));
743                     break;
744                 }
745                 case "type": {
746                     dependency.type(interpolatedTrimmed(nextText(parser, strict), "type"));
747                     break;
748                 }
749                 default: {
750                     checkUnknownElement(parser, strict);
751                     break;
752                 }
753             }
754         }
755         context.removeLast();
756         return dependency.build();
757     }
758 
759 
760     private String checkDuplicate(String tagName, XMLStreamReader parser, Set<String> parsed) throws XMLStreamException {
761         if (!parsed.add(tagName)) {
762             throw new XMLStreamException("Duplicated tag: '" + tagName + "'", parser.getLocation(), null);
763         }
764         return tagName;
765     }
766 
767     /**
768      * Method checkUnknownAttribute.
769      *
770      * @param parser a parser object.
771      * @param strict a strict object.
772      * @param tagName a tagName object.
773      * @param attribute a attribute object.
774      * @throws XMLStreamException XMLStreamException if
775      * any.
776      * @throws IOException IOException if any.
777      */
778     private void checkUnknownAttribute(XMLStreamReader parser, String attribute, String tagName, boolean strict) throws XMLStreamException {
779         // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too
780         if (strict) {
781             throw new XMLStreamException("Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser.getLocation(), null);
782         }
783     } //-- void checkUnknownAttribute(XMLStreamReader, String, String, boolean)
784 
785     /**
786      * Method checkUnknownElement.
787      *
788      * @param parser a parser object.
789      * @param strict a strict object.
790      * @throws XMLStreamException XMLStreamException if
791      * any.
792      * @throws IOException IOException if any.
793      */
794     private void checkUnknownElement(XMLStreamReader parser, boolean strict) throws XMLStreamException {
795         if (strict) {
796             throw new XMLStreamException("Unrecognised tag: '" + parser.getName() + "'", parser.getLocation(), null);
797         }
798 
799         for (int unrecognizedTagCount = 1; unrecognizedTagCount > 0;) {
800             int eventType = nextTag(parser);
801             if (eventType == XMLStreamReader.START_ELEMENT) {
802                 unrecognizedTagCount++;
803             } else if (eventType == XMLStreamReader.END_ELEMENT) {
804                 unrecognizedTagCount--;
805             }
806         }
807     } //-- void checkUnknownElement(XMLStreamReader, boolean)
808 
809     /**
810      * Method getTrimmedValue.
811      *
812      * @param s a s object.
813      * @return String
814      */
815     private String getTrimmedValue(String s) {
816         if (s != null) {
817             s = s.trim();
818         }
819         return s;
820     } //-- String getTrimmedValue(String)
821 
822     /**
823      * Method interpolatedTrimmed.
824      *
825      * @param value a value object.
826      * @param context a context object.
827      * @return String
828      */
829     private String interpolatedTrimmed(String value, String context) {
830         return getTrimmedValue(contentTransformer.transform(value, context));
831     } //-- String interpolatedTrimmed(String, String)
832 
833     /**
834      * Method nextTag.
835      *
836      * @param parser a parser object.
837      * @throws IOException IOException if any.
838      * @throws XMLStreamException XMLStreamException if
839      * any.
840      * @return int
841      */
842     private int nextTag(XMLStreamReader parser) throws XMLStreamException {
843         while (true) {
844             int next = parser.next();
845             switch (next) {
846                 case XMLStreamReader.SPACE:
847                 case XMLStreamReader.COMMENT:
848                 case XMLStreamReader.PROCESSING_INSTRUCTION:
849                 case XMLStreamReader.CDATA:
850                 case XMLStreamReader.CHARACTERS:
851                     continue;
852                 case XMLStreamReader.START_ELEMENT:
853                 case XMLStreamReader.END_ELEMENT:
854                     return next;
855             }
856         }
857     } //-- int nextTag(XMLStreamReader)
858 
859     private String nextText(XMLStreamReader parser, boolean strict) throws XMLStreamException {
860         int eventType = parser.getEventType();
861         if (eventType != XMLStreamReader.START_ELEMENT) {
862             throw new XMLStreamException("parser must be on START_ELEMENT to read next text", parser.getLocation(), null);
863         }
864         eventType = parser.next();
865         StringBuilder result = new StringBuilder();
866         while (true) {
867             if (eventType == XMLStreamReader.CHARACTERS || eventType == XMLStreamReader.CDATA) {
868                 result.append(parser.getText());
869             } else if (eventType == XMLStreamReader.ENTITY_REFERENCE) {
870                 String val = null;
871                 if (strict) {
872                     throw new XMLStreamException("Entities are not supported in strict mode", parser.getLocation(), null);
873                 } else if (addDefaultEntities) {
874                     val = DEFAULT_ENTITIES.get(parser.getLocalName());
875                 }
876                 if (val != null) {
877                     result.append(val);
878                 } else {
879                     result.append("&").append(parser.getLocalName()).append(";");
880                 }
881             } else if (eventType != XMLStreamReader.COMMENT) {
882                 break;
883             }
884             eventType = parser.next();
885         }
886         if (eventType != XMLStreamReader.END_ELEMENT) {
887             throw new XMLStreamException(
888                 "TEXT must be immediately followed by END_ELEMENT and not " + eventType /*TODO: TYPES[eventType]*/, parser.getLocation(), null);
889         }
890         return result.toString();
891     }
892 
893     private XmlNode buildXmlNode(XMLStreamReader parser) throws XMLStreamException {
894         return XmlNodeBuilder.build(parser);
895     }
896 
897     /**
898      * Method getBooleanValue.
899      *
900      * @param s a s object.
901      * @param defaultValue a defaultValue object.
902      * @param parser a parser object.
903      * @param attribute a attribute object.
904      * @throws XMLStreamException XMLStreamException if
905      * any.
906      * @return boolean
907      */
908     private boolean getBooleanValue(String s, String attribute, XMLStreamReader parser, boolean defaultValue) throws XMLStreamException {
909         if (s != null && s.length() != 0) {
910             return Boolean.valueOf(s).booleanValue();
911         }
912         return defaultValue;
913     } //-- boolean getBooleanValue(String, String, XMLStreamReader, String)
914 
915     public static interface ContentTransformer {
916         /**
917          * Interpolate the value read from the xpp3 document
918          * @param source The source value
919          * @param fieldName A description of the field being interpolated. The implementation may use this to
920          *                           log stuff.
921          * @return The interpolated value.
922          */
923         String transform(String source, String fieldName);
924     }
925 
926 }