1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.shared.utils.xml;
20
21 import javax.annotation.Nonnull;
22 import javax.annotation.WillClose;
23
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.InputStreamReader;
27 import java.io.Reader;
28 import java.io.UnsupportedEncodingException;
29 import java.util.ArrayList;
30 import java.util.List;
31
32 import org.apache.maven.shared.utils.xml.pull.XmlPullParserException;
33 import org.xml.sax.Attributes;
34 import org.xml.sax.InputSource;
35 import org.xml.sax.SAXException;
36 import org.xml.sax.XMLReader;
37 import org.xml.sax.helpers.DefaultHandler;
38
39
40
41
42 public class Xpp3DomBuilder {
43
44
45
46
47
48
49 public static Xpp3Dom build(@WillClose @Nonnull Reader reader) throws XmlPullParserException {
50 return build(reader, false);
51 }
52
53
54
55
56
57
58
59 public static Xpp3Dom build(@WillClose InputStream is, @Nonnull String encoding) throws XmlPullParserException {
60 return build(is, encoding, false);
61 }
62
63
64
65
66
67
68
69
70
71 @Deprecated
72 public static Xpp3Dom build(@WillClose InputStream is, @Nonnull String encoding, boolean noop)
73 throws XmlPullParserException {
74 try {
75 Reader reader = new InputStreamReader(is, encoding);
76 return build(reader);
77 } catch (UnsupportedEncodingException e) {
78 throw new XmlPullParserException(e);
79 }
80 }
81
82
83
84
85
86
87
88
89 @Deprecated
90 public static Xpp3Dom build(@WillClose Reader in, boolean noop) throws XmlPullParserException {
91 try (Reader reader = in) {
92 DocHandler docHandler = parseSax(new InputSource(reader));
93 reader.close();
94 return docHandler.result;
95 } catch (final IOException e) {
96 throw new XmlPullParserException(e);
97 }
98 }
99
100 private static DocHandler parseSax(@Nonnull InputSource inputSource) throws XmlPullParserException {
101 try {
102 DocHandler ch = new DocHandler();
103 XMLReader parser = createXmlReader();
104 parser.setContentHandler(ch);
105 parser.parse(inputSource);
106 return ch;
107 } catch (IOException e) {
108 throw new XmlPullParserException(e);
109 } catch (SAXException e) {
110 throw new XmlPullParserException(e);
111 }
112 }
113
114 private static XMLReader createXmlReader() throws SAXException {
115 XMLReader comSunXmlReader = instantiate("com.sun.org.apache.xerces.internal.parsers.SAXParser");
116 if (comSunXmlReader != null) {
117 return comSunXmlReader;
118 }
119
120 String key = "org.xml.sax.driver";
121 String oldParser = System.getProperty(key);
122 System.clearProperty(key);
123
124 try {
125 return org.xml.sax.helpers.XMLReaderFactory.createXMLReader();
126 } finally {
127 if (oldParser != null) {
128 System.setProperty(key, oldParser);
129 }
130 }
131 }
132
133 private static XMLReader instantiate(String s) {
134 try {
135 Class<?> aClass = Thread.currentThread().getContextClassLoader().loadClass(s);
136 return (XMLReader) aClass.newInstance();
137 } catch (ClassNotFoundException e) {
138 return null;
139 } catch (InstantiationException e) {
140 return null;
141 } catch (IllegalAccessException e) {
142 return null;
143 }
144 }
145
146 private static class DocHandler extends DefaultHandler {
147 private final List<Xpp3Dom> elemStack = new ArrayList<Xpp3Dom>();
148
149 private final List<StringBuilder> values = new ArrayList<StringBuilder>();
150
151 Xpp3Dom result = null;
152
153 private boolean spacePreserve = false;
154
155 @Override
156 public void startElement(String uri, String localName, String qName, Attributes attributes)
157 throws SAXException {
158 spacePreserve = false;
159 Xpp3Dom child = new Xpp3Dom(localName);
160
161 attachToParent(child);
162 pushOnStack(child);
163
164 values.add(new StringBuilder());
165
166 int size = attributes.getLength();
167 for (int i = 0; i < size; i++) {
168 String name = attributes.getQName(i);
169 String value = attributes.getValue(i);
170 child.setAttribute(name, value);
171 spacePreserve = spacePreserve || ("xml:space".equals(name) && "preserve".equals(value));
172 }
173 }
174
175 private boolean pushOnStack(Xpp3Dom child) {
176 return elemStack.add(child);
177 }
178
179 private void attachToParent(Xpp3Dom child) {
180 int depth = elemStack.size();
181 if (depth > 0) {
182 elemStack.get(depth - 1).addChild(child);
183 }
184 }
185
186 private Xpp3Dom pop() {
187 int depth = elemStack.size() - 1;
188 return elemStack.remove(depth);
189 }
190
191 @Override
192 public void endElement(String uri, String localName, String qName) throws SAXException {
193 int depth = elemStack.size() - 1;
194
195 Xpp3Dom element = pop();
196
197
198 Object accumulatedValue = values.remove(depth);
199
200 if (element.getChildCount() == 0) {
201 if (accumulatedValue == null) {
202 element.setValue("");
203 } else {
204 element.setValue(accumulatedValue.toString());
205 }
206 }
207
208 if (depth == 0) {
209 result = element;
210 }
211 }
212
213 @Override
214 public void characters(char[] ch, int start, int length) throws SAXException {
215 String text = new String(ch, start, length);
216 appendToTopValue(text);
217 }
218
219 private void appendToTopValue(String toAppend) {
220
221 StringBuilder stringBuilder = values.get(values.size() - 1);
222 stringBuilder.append(toAppend);
223 }
224 }
225 }