Home | History | Annotate | Download | only in service
      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