1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.support.v7.mms;
18 
19 import android.util.Log;
20 
21 import org.xmlpull.v1.XmlPullParser;
22 import org.xmlpull.v1.XmlPullParserException;
23 
24 import java.io.IOException;
25 
26 /**
27  * Base class for a parser of XML resources
28  */
29 abstract class MmsXmlResourceParser {
30     /**
31      * Parse the content
32      *
33      * @throws IOException
34      * @throws XmlPullParserException
35      */
parseRecord()36     protected abstract void parseRecord() throws IOException, XmlPullParserException;
37 
38     /**
39      * Get the root tag of the content
40      *
41      * @return the text of root tag
42      */
getRootTag()43     protected abstract String getRootTag();
44 
45     private final StringBuilder mLogStringBuilder = new StringBuilder();
46 
47     protected final XmlPullParser mInputParser;
48 
MmsXmlResourceParser(XmlPullParser parser)49     protected MmsXmlResourceParser(XmlPullParser parser) {
50         mInputParser = parser;
51     }
52 
parse()53     void parse() {
54         try {
55             // Find the first element
56             if (advanceToNextEvent(XmlPullParser.START_TAG) != XmlPullParser.START_TAG) {
57                 throw new XmlPullParserException("ApnsXmlProcessor: expecting start tag @"
58                         + xmlParserDebugContext());
59             }
60             if (!getRootTag().equals(mInputParser.getName())) {
61                 Log.w(MmsService.TAG, "Carrier config does not start with " + getRootTag());
62                 return;
63             }
64             // We are at the start tag
65             for (;;) {
66                 int nextEvent;
67                 // Skipping spaces
68                 while ((nextEvent = mInputParser.next()) == XmlPullParser.TEXT);
69                 if (nextEvent == XmlPullParser.START_TAG) {
70                     // Parse one record
71                     parseRecord();
72                 } else if (nextEvent == XmlPullParser.END_TAG) {
73                     break;
74                 } else {
75                     throw new XmlPullParserException("Expecting start or end tag @"
76                             + xmlParserDebugContext());
77                 }
78             }
79         } catch (IOException e) {
80             Log.w(MmsService.TAG, "XmlResourceParser: I/O failure", e);
81         } catch (XmlPullParserException e) {
82             Log.w(MmsService.TAG, "XmlResourceParser: parsing failure", e);
83         }
84     }
85 
86     /**
87      * Move XML parser forward to next event type or the end of doc
88      *
89      * @param eventType
90      * @return The final event type we meet
91      * @throws XmlPullParserException
92      * @throws IOException
93      */
advanceToNextEvent(int eventType)94     protected int advanceToNextEvent(int eventType) throws XmlPullParserException, IOException {
95         for (;;) {
96             int nextEvent = mInputParser.next();
97             if (nextEvent == eventType
98                     || nextEvent == XmlPullParser.END_DOCUMENT) {
99                 return nextEvent;
100             }
101         }
102     }
103 
104     /**
105      * @return The debugging information of the parser's current position
106      */
xmlParserDebugContext()107     protected String xmlParserDebugContext() {
108         mLogStringBuilder.setLength(0);
109         if (mInputParser != null) {
110             try {
111                 final int eventType = mInputParser.getEventType();
112                 mLogStringBuilder.append(xmlParserEventString(eventType));
113                 if (eventType == XmlPullParser.START_TAG
114                         || eventType == XmlPullParser.END_TAG
115                         || eventType == XmlPullParser.TEXT) {
116                     mLogStringBuilder.append('<').append(mInputParser.getName());
117                     for (int i = 0; i < mInputParser.getAttributeCount(); i++) {
118                         mLogStringBuilder.append(' ')
119                                 .append(mInputParser.getAttributeName(i))
120                                 .append('=')
121                                 .append(mInputParser.getAttributeValue(i));
122                     }
123                     mLogStringBuilder.append("/>");
124                 }
125                 return mLogStringBuilder.toString();
126             } catch (XmlPullParserException e) {
127                 Log.w(MmsService.TAG, "XmlResourceParser exception", e);
128             }
129         }
130         return "Unknown";
131     }
132 
xmlParserEventString(int event)133     private static String xmlParserEventString(int event) {
134         switch (event) {
135             case XmlPullParser.START_DOCUMENT: return "START_DOCUMENT";
136             case XmlPullParser.END_DOCUMENT: return "END_DOCUMENT";
137             case XmlPullParser.START_TAG: return "START_TAG";
138             case XmlPullParser.END_TAG: return "END_TAG";
139             case XmlPullParser.TEXT: return "TEXT";
140         }
141         return Integer.toString(event);
142     }
143 }
144