1package eu.siacs.conversations.xml;
2
3import java.io.IOException;
4import java.io.InputStream;
5import java.io.InputStreamReader;
6
7import org.xmlpull.v1.XmlPullParser;
8import org.xmlpull.v1.XmlPullParserException;
9
10import android.os.PowerManager;
11import android.os.PowerManager.WakeLock;
12import android.util.Log;
13import android.util.Xml;
14
15public class XmlReader {
16 private static final String LOGTAG = "xmppService";
17 private XmlPullParser parser;
18 private PowerManager.WakeLock wakeLock;
19 private InputStream is;
20
21 public XmlReader(WakeLock wakeLock) {
22 this.parser = Xml.newPullParser();
23 try {
24 this.parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES,true);
25 } catch (XmlPullParserException e) {
26 Log.d(LOGTAG,"error setting namespace feature on parser");
27 }
28 this.wakeLock = wakeLock;
29 }
30
31 public void setInputStream(InputStream inputStream) throws IOException {
32 if (inputStream==null) {
33 throw new IOException();
34 }
35 this.is = inputStream;
36 try {
37 parser.setInput(new InputStreamReader(this.is));
38 } catch (XmlPullParserException e) {
39 throw new IOException("error resetting parser");
40 }
41 }
42
43 public InputStream getInputStream() throws IOException {
44 if (this.is==null) {
45 throw new IOException();
46 }
47 return is;
48 }
49
50 public void reset() throws IOException {
51 if (this.is==null) {
52 throw new IOException();
53 }
54 try {
55 parser.setInput(new InputStreamReader(this.is));
56 } catch (XmlPullParserException e) {
57 throw new IOException("error resetting parser");
58 }
59 }
60
61 public Tag readTag() throws XmlPullParserException, IOException {
62 if (wakeLock.isHeld()) {
63 try { wakeLock.release();} catch (RuntimeException re) {}
64 }
65 try {
66 while(this.is != null && parser.next() != XmlPullParser.END_DOCUMENT) {
67 wakeLock.acquire();
68 if (parser.getEventType() == XmlPullParser.START_TAG) {
69 Tag tag = Tag.start(parser.getName());
70 for(int i = 0; i < parser.getAttributeCount(); ++i) {
71 tag.setAttribute(parser.getAttributeName(i), parser.getAttributeValue(i));
72 }
73 String xmlns = parser.getNamespace();
74 if (xmlns!=null) {
75 tag.setAttribute("xmlns",xmlns);
76 }
77 return tag;
78 } else if (parser.getEventType() == XmlPullParser.END_TAG) {
79 Tag tag = Tag.end(parser.getName());
80 return tag;
81 } else if (parser.getEventType() == XmlPullParser.TEXT) {
82 Tag tag = Tag.no(parser.getText());
83 return tag;
84 }
85 }
86 if (wakeLock.isHeld()) {
87 try { wakeLock.release();} catch (RuntimeException re) {}
88 }
89 } catch (ArrayIndexOutOfBoundsException e) {
90 throw new IOException("xml parser mishandled ArrayIndexOufOfBounds", e);
91 } catch (StringIndexOutOfBoundsException e) {
92 throw new IOException("xml parser mishandled StringIndexOufOfBounds", e);
93 } catch (NullPointerException e) {
94 throw new IOException("xml parser mishandled NullPointerException", e);
95 } catch (IndexOutOfBoundsException e) {
96 throw new IOException("xml parser mishandled IndexOutOfBound", e);
97 }
98 return null;
99 }
100
101 public Element readElement(Tag currentTag) throws XmlPullParserException, IOException {
102 Element element = new Element(currentTag.getName());
103 element.setAttributes(currentTag.getAttributes());
104 Tag nextTag = this.readTag();
105 if (nextTag == null) {
106 throw new IOException("unterupted mid tag");
107 }
108 if(nextTag.isNo()) {
109 element.setContent(nextTag.getName());
110 nextTag = this.readTag();
111 if (nextTag == null) {
112 throw new IOException("unterupted mid tag");
113 }
114 }
115 while(!nextTag.isEnd(element.getName())) {
116 if (!nextTag.isNo()) {
117 Element child = this.readElement(nextTag);
118 element.addChild(child);
119 }
120 nextTag = this.readTag();
121 if (nextTag == null) {
122 throw new IOException("unterupted mid tag");
123 }
124 }
125 return element;
126 }
127}