1 package org.codehaus.plexus.util.xml;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.Reader;
22 import java.util.ArrayList;
23 import java.util.List;
24
25 import org.codehaus.plexus.util.IOUtil;
26 import org.codehaus.plexus.util.xml.pull.MXParser;
27 import org.codehaus.plexus.util.xml.pull.XmlPullParser;
28 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
29
30
31
32
33 public class Xpp3DomBuilder {
34 private static final boolean DEFAULT_TRIM = true;
35
36 public static Xpp3Dom build(Reader reader) throws XmlPullParserException, IOException {
37 return build(reader, null);
38 }
39
40
41
42
43
44
45
46
47
48 public static Xpp3Dom build(Reader reader, InputLocationBuilder locationBuilder)
49 throws XmlPullParserException, IOException {
50 return build(reader, DEFAULT_TRIM, locationBuilder);
51 }
52
53 public static Xpp3Dom build(InputStream is, String encoding) throws XmlPullParserException, IOException {
54 return build(is, encoding, DEFAULT_TRIM);
55 }
56
57 public static Xpp3Dom build(InputStream is, String encoding, boolean trim)
58 throws XmlPullParserException, IOException {
59 try {
60 final XmlPullParser parser = new MXParser();
61 parser.setInput(is, encoding);
62
63 final Xpp3Dom xpp3Dom = build(parser, trim);
64 is.close();
65 is = null;
66
67 return xpp3Dom;
68 } finally {
69 IOUtil.close(is);
70 }
71 }
72
73 public static Xpp3Dom build(Reader reader, boolean trim) throws XmlPullParserException, IOException {
74 return build(reader, trim, null);
75 }
76
77
78
79
80
81
82
83
84
85
86 public static Xpp3Dom build(Reader reader, boolean trim, InputLocationBuilder locationBuilder)
87 throws XmlPullParserException, IOException {
88 try {
89 final XmlPullParser parser = new MXParser();
90 parser.setInput(reader);
91
92 final Xpp3Dom xpp3Dom = build(parser, trim, locationBuilder);
93 reader.close();
94 reader = null;
95
96 return xpp3Dom;
97 } finally {
98 IOUtil.close(reader);
99 }
100 }
101
102 public static Xpp3Dom build(XmlPullParser parser) throws XmlPullParserException, IOException {
103 return build(parser, DEFAULT_TRIM);
104 }
105
106 public static Xpp3Dom build(XmlPullParser parser, boolean trim) throws XmlPullParserException, IOException {
107 return build(parser, trim, null);
108 }
109
110
111
112
113
114
115
116
117
118
119 public static Xpp3Dom build(XmlPullParser parser, boolean trim, InputLocationBuilder locationBuilder)
120 throws XmlPullParserException, IOException {
121 List<Xpp3Dom> elements = new ArrayList<>();
122
123 List<StringBuilder> values = new ArrayList<>();
124
125 int eventType = parser.getEventType();
126
127 boolean spacePreserve = false;
128
129 while (eventType != XmlPullParser.END_DOCUMENT) {
130 if (eventType == XmlPullParser.START_TAG) {
131 spacePreserve = false;
132
133 String rawName = parser.getName();
134
135 Xpp3Dom childConfiguration = new Xpp3Dom(rawName);
136
137 if (locationBuilder != null) {
138 childConfiguration.setInputLocation(locationBuilder.toInputLocation(parser));
139 }
140
141 int depth = elements.size();
142
143 if (depth > 0) {
144 Xpp3Dom parent = elements.get(depth - 1);
145
146 parent.addChild(childConfiguration);
147 }
148
149 elements.add(childConfiguration);
150
151 if (parser.isEmptyElementTag()) {
152 values.add(null);
153 } else {
154 values.add(new StringBuilder());
155 }
156
157 int attributesSize = parser.getAttributeCount();
158
159 for (int i = 0; i < attributesSize; i++) {
160 String name = parser.getAttributeName(i);
161
162 String value = parser.getAttributeValue(i);
163
164 childConfiguration.setAttribute(name, value);
165
166 spacePreserve = spacePreserve || ("xml:space".equals(name) && "preserve".equals(value));
167 }
168 } else if (eventType == XmlPullParser.TEXT) {
169 int depth = values.size() - 1;
170
171 @SuppressWarnings("MismatchedQueryAndUpdateOfStringBuilder")
172 StringBuilder valueBuffer = values.get(depth);
173
174 String text = parser.getText();
175
176 if (trim && !spacePreserve) {
177 text = text.trim();
178 }
179
180 valueBuffer.append(text);
181 } else if (eventType == XmlPullParser.END_TAG) {
182 int depth = elements.size() - 1;
183
184 Xpp3Dom finishedConfiguration = elements.remove(depth);
185
186
187 Object accumulatedValue = values.remove(depth);
188
189 if (finishedConfiguration.getChildCount() == 0) {
190 if (accumulatedValue == null) {
191 finishedConfiguration.setValue(null);
192 } else {
193 finishedConfiguration.setValue(accumulatedValue.toString());
194 }
195 }
196
197 if (depth == 0) {
198 return finishedConfiguration;
199 }
200 }
201
202 eventType = parser.next();
203 }
204
205 throw new IllegalStateException("End of document found before returning to 0 depth");
206 }
207
208
209
210
211
212
213 public static interface InputLocationBuilder {
214 Object toInputLocation(XmlPullParser parser);
215 }
216 }