1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package org.apache.maven.internal.xml;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.io.Reader;
24  import java.util.ArrayList;
25  import java.util.HashMap;
26  import java.util.List;
27  import java.util.Map;
28  
29  import org.apache.maven.api.xml.XmlNode;
30  import org.codehaus.plexus.util.IOUtil;
31  import org.codehaus.plexus.util.xml.pull.MXParser;
32  import org.codehaus.plexus.util.xml.pull.XmlPullParser;
33  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
34  
35  
36  
37  
38  public class XmlNodeBuilder {
39      private static final boolean DEFAULT_TRIM = true;
40  
41      public static XmlNodeImpl build(Reader reader) throws XmlPullParserException, IOException {
42          return build(reader, null);
43      }
44  
45      
46  
47  
48  
49  
50  
51  
52  
53      public static XmlNodeImpl build(Reader reader, InputLocationBuilder locationBuilder)
54              throws XmlPullParserException, IOException {
55          return build(reader, DEFAULT_TRIM, locationBuilder);
56      }
57  
58      public static XmlNodeImpl build(InputStream is, String encoding) throws XmlPullParserException, IOException {
59          return build(is, encoding, DEFAULT_TRIM);
60      }
61  
62      public static XmlNodeImpl build(InputStream is, String encoding, boolean trim)
63              throws XmlPullParserException, IOException {
64          try {
65              final XmlPullParser parser = new MXParser();
66              parser.setInput(is, encoding);
67  
68              final XmlNodeImpl node = build(parser, trim);
69              is.close();
70              is = null;
71  
72              return node;
73          } finally {
74              IOUtil.close(is);
75          }
76      }
77  
78      public static XmlNodeImpl build(Reader reader, boolean trim) throws XmlPullParserException, IOException {
79          return build(reader, trim, null);
80      }
81  
82      
83  
84  
85  
86  
87  
88  
89  
90  
91      public static XmlNodeImpl build(Reader reader, boolean trim, InputLocationBuilder locationBuilder)
92              throws XmlPullParserException, IOException {
93          try {
94              final XmlPullParser parser = new MXParser();
95              parser.setInput(reader);
96  
97              final XmlNodeImpl node = build(parser, trim, locationBuilder);
98              reader.close();
99              reader = null;
100 
101             return node;
102         } finally {
103             IOUtil.close(reader);
104         }
105     }
106 
107     public static XmlNodeImpl build(XmlPullParser parser) throws XmlPullParserException, IOException {
108         return build(parser, DEFAULT_TRIM);
109     }
110 
111     public static XmlNodeImpl build(XmlPullParser parser, boolean trim) throws XmlPullParserException, IOException {
112         return build(parser, trim, null);
113     }
114 
115     
116 
117 
118 
119 
120 
121 
122 
123 
124     public static XmlNodeImpl build(XmlPullParser parser, boolean trim, InputLocationBuilder locationBuilder)
125             throws XmlPullParserException, IOException {
126         boolean spacePreserve = false;
127         String name = null;
128         String value = null;
129         Object location = null;
130         Map<String, String> attrs = null;
131         List<XmlNode> children = null;
132         int eventType = parser.getEventType();
133         boolean emptyTag = false;
134         while (eventType != XmlPullParser.END_DOCUMENT) {
135             if (eventType == XmlPullParser.START_TAG) {
136                 emptyTag = parser.isEmptyElementTag();
137                 if (name == null) {
138                     name = parser.getName();
139                     location = locationBuilder != null ? locationBuilder.toInputLocation(parser) : null;
140                     int attributesSize = parser.getAttributeCount();
141                     if (attributesSize > 0) {
142                         attrs = new HashMap<>();
143                         for (int i = 0; i < attributesSize; i++) {
144                             String aname = parser.getAttributeName(i);
145                             String avalue = parser.getAttributeValue(i);
146                             attrs.put(aname, avalue);
147                             spacePreserve = spacePreserve || ("xml:space".equals(aname) && "preserve".equals(avalue));
148                         }
149                     }
150                 } else {
151                     if (children == null) {
152                         children = new ArrayList<>();
153                     }
154                     XmlNode child = build(parser, trim, locationBuilder);
155                     children.add(child);
156                 }
157             } else if (eventType == XmlPullParser.TEXT) {
158                 String text = parser.getText();
159                 if (trim && !spacePreserve) {
160                     text = text.trim();
161                 }
162                 value = value != null ? value + text : text;
163             } else if (eventType == XmlPullParser.END_TAG) {
164                 return new XmlNodeImpl(
165                         name,
166                         children == null ? (value != null ? value : emptyTag ? null : "") : null,
167                         attrs,
168                         children,
169                         location);
170             }
171             eventType = parser.next();
172         }
173         throw new IllegalStateException("End of document found before returning to 0 depth");
174     }
175 
176     
177 
178 
179 
180 
181     public interface InputLocationBuilder {
182         Object toInputLocation(XmlPullParser parser);
183     }
184 }