1 /* 2 * Copyright (C) 2014 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 com.android.mms.service; 18 19 import org.xmlpull.v1.XmlPullParser; 20 import org.xmlpull.v1.XmlPullParserException; 21 22 import android.content.ContentValues; 23 import android.util.Log; 24 25 import java.io.IOException; 26 27 /* 28 * XML processor for mms_config.xml 29 */ 30 public class MmsConfigXmlProcessor { 31 private static final String TAG = MmsService.TAG; 32 33 public interface MmsConfigHandler { 34 public void process(String key, String value, String type); 35 } 36 37 private static final String TAG_MMS_CONFIG = "mms_config"; 38 39 // Handler to process one mms_config key/value pair 40 private MmsConfigHandler mMmsConfigHandler; 41 42 private final StringBuilder mLogStringBuilder = new StringBuilder(); 43 44 private final XmlPullParser mInputParser; 45 46 private MmsConfigXmlProcessor(XmlPullParser parser) { 47 mInputParser = parser; 48 mMmsConfigHandler = null; 49 } 50 51 public static MmsConfigXmlProcessor get(XmlPullParser parser) { 52 return new MmsConfigXmlProcessor(parser); 53 } 54 55 public MmsConfigXmlProcessor setMmsConfigHandler(MmsConfigHandler handler) { 56 mMmsConfigHandler = handler; 57 return this; 58 } 59 60 /** 61 * Move XML parser forward to next event type or the end of doc 62 * 63 * @param eventType 64 * @return The final event type we meet 65 * @throws org.xmlpull.v1.XmlPullParserException 66 * @throws java.io.IOException 67 */ 68 private int advanceToNextEvent(int eventType) throws XmlPullParserException, IOException { 69 for (;;) { 70 int nextEvent = mInputParser.next(); 71 if (nextEvent == eventType 72 || nextEvent == XmlPullParser.END_DOCUMENT) { 73 return nextEvent; 74 } 75 } 76 } 77 78 public void process() { 79 try { 80 // Find the first element 81 if (advanceToNextEvent(XmlPullParser.START_TAG) != XmlPullParser.START_TAG) { 82 throw new XmlPullParserException("MmsConfigXmlProcessor: expecting start tag @" 83 + xmlParserDebugContext()); 84 } 85 // A single ContentValues object for holding the parsing result of 86 // an apn element 87 final ContentValues values = new ContentValues(); 88 String tagName = mInputParser.getName(); 89 // Top level tag can be "apns" (apns.xml, or APN OTA XML) 90 // or "mms_config" (mms_config.xml) 91 if (TAG_MMS_CONFIG.equals(tagName)) { 92 // mms_config.xml resource 93 processMmsConfig(); 94 } 95 } catch (IOException e) { 96 Log.e(TAG, "MmsConfigXmlProcessor: I/O failure " + e, e); 97 } catch (XmlPullParserException e) { 98 Log.e(TAG, "MmsConfigXmlProcessor: parsing failure " + e, e); 99 } 100 } 101 102 private static String xmlParserEventString(int event) { 103 switch (event) { 104 case XmlPullParser.START_DOCUMENT: return "START_DOCUMENT"; 105 case XmlPullParser.END_DOCUMENT: return "END_DOCUMENT"; 106 case XmlPullParser.START_TAG: return "START_TAG"; 107 case XmlPullParser.END_TAG: return "END_TAG"; 108 case XmlPullParser.TEXT: return "TEXT"; 109 } 110 return Integer.toString(event); 111 } 112 113 /** 114 * @return The debugging information of the parser's current position 115 */ 116 private String xmlParserDebugContext() { 117 mLogStringBuilder.setLength(0); 118 if (mInputParser != null) { 119 try { 120 final int eventType = mInputParser.getEventType(); 121 mLogStringBuilder.append(xmlParserEventString(eventType)); 122 if (eventType == XmlPullParser.START_TAG 123 || eventType == XmlPullParser.END_TAG 124 || eventType == XmlPullParser.TEXT) { 125 mLogStringBuilder.append('<').append(mInputParser.getName()); 126 for (int i = 0; i < mInputParser.getAttributeCount(); i++) { 127 mLogStringBuilder.append(' ') 128 .append(mInputParser.getAttributeName(i)) 129 .append('=') 130 .append(mInputParser.getAttributeValue(i)); 131 } 132 mLogStringBuilder.append("/>"); 133 } 134 return mLogStringBuilder.toString(); 135 } catch (XmlPullParserException e) { 136 Log.e(TAG, "xmlParserDebugContext: " + e, e); 137 } 138 } 139 return "Unknown"; 140 } 141 142 /** 143 * Process one mms_config. 144 * 145 * @throws java.io.IOException 146 * @throws org.xmlpull.v1.XmlPullParserException 147 */ 148 private void processMmsConfig() 149 throws IOException, XmlPullParserException { 150 // We are at the start tag 151 for (;;) { 152 int nextEvent; 153 // Skipping spaces 154 while ((nextEvent = mInputParser.next()) == XmlPullParser.TEXT); 155 if (nextEvent == XmlPullParser.START_TAG) { 156 // Parse one mms config key/value 157 processMmsConfigKeyValue(); 158 } else if (nextEvent == XmlPullParser.END_TAG) { 159 break; 160 } else { 161 throw new XmlPullParserException("MmsConfig: expecting start or end tag @" 162 + xmlParserDebugContext()); 163 } 164 } 165 } 166 167 /** 168 * Process one mms_config key/value pair 169 * 170 * @throws java.io.IOException 171 * @throws org.xmlpull.v1.XmlPullParserException 172 */ 173 private void processMmsConfigKeyValue() throws IOException, XmlPullParserException { 174 final String key = mInputParser.getAttributeValue(null, "name"); 175 // We are at the start tag, the name of the tag is the type 176 // e.g. <int name="key">value</int> 177 final String type = mInputParser.getName(); 178 int nextEvent = mInputParser.next(); 179 String value = null; 180 if (nextEvent == XmlPullParser.TEXT) { 181 value = mInputParser.getText(); 182 nextEvent = mInputParser.next(); 183 } 184 if (nextEvent != XmlPullParser.END_TAG) { 185 throw new XmlPullParserException("MmsConfigXmlProcessor: expecting end tag @" 186 + xmlParserDebugContext()); 187 } 188 if (MmsConfig.isValidKey(key, type)) { 189 // We are done parsing one mms_config key/value, call the handler 190 if (mMmsConfigHandler != null) { 191 mMmsConfigHandler.process(key, value, type); 192 } 193 } else { 194 Log.w(TAG, "MmsConfig: invalid key=" + key + " or type=" + type); 195 } 196 } 197 } 198