📄 ptsprimitiveparser.java
字号:
/* * Copyright (C) 2007 Esmertec AG. * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.android.im.imps;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.HashMap;import java.util.Map.Entry;import java.util.regex.Matcher;import java.util.regex.Pattern;import com.android.im.imps.Primitive.TransactionMode;/** * PTS/SMS encoded IMPS messages parser. Only response transactions and * server initiated requests are supported. */public class PtsPrimitiveParser implements PrimitiveParser { // WVaaBBcccDD <parameters> // aa - version number; 12 for 1.2, 13 for 1.3; "XX" for version discovery // BB - message type, case insensitive // ccc - transaction id in range 0-999 without preceding zero // DD - multiple SMSes identifier private static final Pattern sPreamplePattern = Pattern.compile("\\AWV(\\d{2})(\\p{Alpha}{2})(\\d{1,3})(\\p{Alpha}{2})?(\\z| .*)"); private char mReadBuf[] = new char[256]; private StringBuilder mStringBuf = new StringBuilder(); private int mPos; private static int UNCERTAIN_GROUP_SIZE = -1; public Primitive parse(InputStream in) throws ParserException, IOException { // assuming PTS data is always short BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8")); mStringBuf.setLength(0); mPos = 0; int len; while ((len = reader.read(mReadBuf)) != -1) { mStringBuf.append(mReadBuf, 0, len); } return parsePrim(); } private Primitive parsePrim() throws ParserException { Matcher m = sPreamplePattern.matcher(mStringBuf); if (!m.matches()) { throw new ParserException("Invalid PTS encoded message"); } Primitive p = new Primitive(); // TODO: handle WV version in m.group(1) String type = m.group(2).toUpperCase(); String transactionType = PtsCodes.getTransaction(type); if (transactionType == null) { throw new ParserException("Unrecognized transaction code " + type); } p.setContentElement(transactionType); if (PtsCodes.isServerRequestCode(type)) { p.setTransactionMode(TransactionMode.Request); } else { p.setTransactionMode(TransactionMode.Response); } p.setTransactionId(m.group(3)); mPos = m.start(5); if (mPos < mStringBuf.length()) { match(' '); HashMap<String, ParamValue> params = parseParams(); for (Entry<String, ParamValue> param : params.entrySet()) { translateParam(p, param.getKey(), param.getValue()); } } return p; } private static HashMap<String, Integer> sInfoElemTypeMap; private static final int ELEM_OTHER_SIMPLE = 0; private static final int ELEM_SESSION_ID = 1; private static final int ELEM_RESULT = 2; private static final int ELEM_ALL_FUNCTIONS = 3; private static final int ELEM_NOT_AVAIL_FUNCS = 4; private static final int ELEM_CAPABILITY_LIST = 5; private static final int ELEM_CONTACT_LIST = 6; private static final int ELEM_DEFAULT_CONTACT_LIST = 7; private static final int ELEM_USER_NICK_LIST = 8; private static final int ELEM_CONTACT_LIST_PROPS = 9; private static final int ELEM_PRESENCE = 10; /* private static final int ELEM_RESULT_CLIST = 3; private static final int ELEM_RESULT_DOMAIN = 4; private static final int ELEM_RESULT_GROUP = 5; private static final int ELEM_RESULT_MSGID = 6; private static final int ELEM_RESULT_SCRNAME = 7; private static final int ELEM_RESULT_USER = 8; */ static { sInfoElemTypeMap = new HashMap<String, Integer>(); sInfoElemTypeMap.put(PtsCodes.SessionID, ELEM_SESSION_ID); sInfoElemTypeMap.put(PtsCodes.Status, ELEM_RESULT); sInfoElemTypeMap.put(PtsCodes.NotAvailableFunctions, ELEM_NOT_AVAIL_FUNCS); sInfoElemTypeMap.put(PtsCodes.AllFunctions, ELEM_ALL_FUNCTIONS); sInfoElemTypeMap.put(PtsCodes.AgreedCapabilityList, ELEM_CAPABILITY_LIST); sInfoElemTypeMap.put(PtsCodes.ContactList, ELEM_CONTACT_LIST); sInfoElemTypeMap.put(PtsCodes.DefaultContactList, ELEM_DEFAULT_CONTACT_LIST); sInfoElemTypeMap.put(PtsCodes.UserNickList, ELEM_USER_NICK_LIST); sInfoElemTypeMap.put(PtsCodes.ContactListProps, ELEM_CONTACT_LIST_PROPS); sInfoElemTypeMap.put(PtsCodes.Presence, ELEM_PRESENCE); } private static void translateParam(Primitive p, String elemCode, ParamValue elemValue) throws ParserException { int type; elemCode = elemCode.toUpperCase(); // FIXME: Should be refactored when we had concrete situation of the null value case if (elemValue == null) { throw new ParserException("Parameter " + elemCode + " must have value."); } if (sInfoElemTypeMap.containsKey(elemCode)) { type = sInfoElemTypeMap.get(elemCode); /* if (type == ELEM_RESULT_CLIST && p.getType().equals(ImpsTags.Login_Response)) { // Fix up DigestSchema which shares a same code with // ContactListID. It appears only in Login_Response. type = ELEM_OTHER_SIMPLE; } */ } else { type = ELEM_OTHER_SIMPLE; } switch (type) { case ELEM_SESSION_ID: if (elemValue.mStrValue == null) { throw new ParserException("Element SessionID must have string value!"); } if (p.getType().equals(ImpsTags.Login_Response)) { p.addElement(ImpsTags.SessionID, elemValue.mStrValue); } else { p.setSession(elemValue.mStrValue); } break; case ELEM_RESULT: // ST=<StatusCode> // ST=(<StatusCode>,<Description>) PrimitiveElement result = p.addElement(ImpsTags.Result); if (elemValue.mStrValue != null) { result.addChild(ImpsTags.Code, elemValue.mStrValue); } else { checkGroupValue(elemValue.mValueGroup, 2); result.addChild(ImpsTags.Code, elemValue.mValueGroup.get(0).mStrValue); result.addChild(ImpsTags.Description, elemValue.mValueGroup.get(1).mStrValue); } break; case ELEM_ALL_FUNCTIONS: case ELEM_NOT_AVAIL_FUNCS: p.addElement(translateServiceTree(elemCode, elemValue)); break; case ELEM_CAPABILITY_LIST: p.addElement(translateCapabilityList(elemValue)); break; case ELEM_CONTACT_LIST: if (elemValue.mStrValue != null) { p.addElement(ImpsTags.ContactList, elemValue.mStrValue); } else { checkGroupValue(elemValue.mValueGroup, UNCERTAIN_GROUP_SIZE); for (ParamValue value : elemValue.mValueGroup) { p.addElement(ImpsTags.ContactList, value.mStrValue); } } break; case ELEM_DEFAULT_CONTACT_LIST: if (elemValue.mStrValue == null) { throw new ParserException("Deafult Contact List must have string value!"); } p.addElement(ImpsTags.DefaultContactList, elemValue.mStrValue); break; case ELEM_USER_NICK_LIST: { checkGroupValue(elemValue.mValueGroup, UNCERTAIN_GROUP_SIZE); PrimitiveElement nicklistElem = p.addElement(ImpsTags.NickList); int groupSize = elemValue.mValueGroup.size(); for (int i = 0; i < groupSize; i++) { ArrayList<ParamValue> valueGroup = elemValue.mValueGroup.get(i).mValueGroup; checkGroupValue(valueGroup, 2); String nickname = valueGroup.get(0).mStrValue; String address = valueGroup.get(1).mStrValue; if (nickname == null || address == null) { throw new ParserException("Null value found for NickName: " + nickname + "-" + address); } PrimitiveElement nicknameElem = nicklistElem.addChild(ImpsTags.NickName); nicknameElem.addChild(ImpsTags.Name, "".equals(nickname) ? null : nickname); nicknameElem.addChild(ImpsTags.UserID, address); } } break; case ELEM_CONTACT_LIST_PROPS: { checkGroupValue(elemValue.mValueGroup, UNCERTAIN_GROUP_SIZE); PrimitiveElement propertiesElem = p.addElement(ImpsTags.ContactListProperties); int groupSize = elemValue.mValueGroup.size(); for (int i = 0; i < groupSize; i++) { ArrayList<ParamValue> valueGroup = elemValue.mValueGroup.get(i).mValueGroup; checkGroupValue(valueGroup, 2); String name = valueGroup.get(0).mStrValue; String value = valueGroup.get(1).mStrValue; if (name == null || value == null) { throw new ParserException("Null value found for property: " + name + "-" + value); } if (PtsCodes.DisplayName.equals(name)) { name = ImpsConstants.DisplayName; } else if (PtsCodes.Default.equals(name)) { name = ImpsConstants.Default; } else { throw new ParserException("Unrecognized property " + name); } PrimitiveElement propertyElem = propertiesElem.addChild(ImpsTags.Property); propertyElem.addChild(ImpsTags.Name, name); propertyElem.addChild(ImpsTags.Value, value); } } break; case ELEM_PRESENCE: //PR=(<UserID>[,<PresenceSubList>]) //PR=((<UserID>[,<PresenceSubList>]),(<UserID>[,<PresenceSubList>])) checkGroupValue(elemValue.mValueGroup, UNCERTAIN_GROUP_SIZE); if (elemValue.mValueGroup.size() == 1) { // PR=(<UserID>) ParamValue value = elemValue.mValueGroup.get(0); if (value.mStrValue != null) { p.addElement(ImpsTags.Presence).addChild(ImpsTags.UserID, value.mStrValue); } else { // workaround for OZ server p.addElement(translatePresence(value.mValueGroup)); } } else { if (elemValue.mValueGroup.get(0).mStrValue == null) { // PR=((<UserID>[,<PresenceSubList>]),(<UserID>[,<PresenceSubList>])) int groupSize = elemValue.mValueGroup.size(); for (int i = 0; i < groupSize; i++) { ParamValue value = elemValue.mValueGroup.get(i); if (value.mStrValue != null) { p.addElement(ImpsTags.Presence).addChild(ImpsTags.UserID, value.mStrValue); } else { p.addElement(translatePresence(value.mValueGroup)); } } } else { // PR=(<UserID>,<PresenceSubList>) p.addElement(translatePresence(elemValue.mValueGroup)); } } break; case ELEM_OTHER_SIMPLE: p.addElement(translateSimpleElem(elemCode, elemValue)); break; default: throw new ParserException("Unsupported element " + elemValue); } } private static PrimitiveElement translatePresence(ArrayList<ParamValue> valueGroup) throws ParserException { checkGroupValue(valueGroup, UNCERTAIN_GROUP_SIZE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -