/* * Funambol is a mobile platform developed by Funambol, Inc. * Copyright (C) 2009 Funambol, Inc. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License version 3 as published by * the Free Software Foundation with the addition of the following permission * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with this program; if not, see http://www.gnu.org/licenses or write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA. * * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com. * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU Affero General Public License version 3. * * In accordance with Section 7(b) of the GNU Affero General Public License * version 3, these Appropriate Legal Notices must retain the display of the * "Powered by Funambol" logo. If the display of the logo is not reasonably * feasible for technical reasons, the Appropriate Legal Notices must display * the words "Powered by Funambol". */ package com.funambol.syncml.spds; import java.io.OutputStream; import java.io.IOException; import java.util.Vector; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlSerializer; //import org.xmlpull.v1.XmlPullParserFactory; import com.funambol.org.kxml2.io.KXmlParser; import com.funambol.org.kxml2.io.KXmlSerializer; // For WBXML support import com.funambol.org.kxml2.wap.WbxmlSerializer; import com.funambol.org.kxml2.wap.Wbxml; import com.funambol.syncml.protocol.*; import com.funambol.util.Log; /** * This class represents a formatter for SyncML. A formatter is intented to * generate SyncML messages starting from an abstract representation of the same * message. In this current implementation the formatter is not yet connected to * the abstract implementation and it performs a sort of low level formatting * where the bit and pieces of a message are printed together to form the * outgoing message. * The current implementation supports only plain XML but the class aims at * supporting WBXML at some point. */ public class SyncMLFormatter { private static final String TAG_LOG = "SyncMLFormatter"; private static final String METINF = "syncml:metinf"; private XmlSerializer formatter; private OutputStream os; private boolean wbxml = true; private boolean prettyPrint = false; private boolean hideData = false; public SyncMLFormatter(boolean wbxml) { this.wbxml = wbxml; } public void setHideData(boolean hideData) { this.hideData = hideData; } public void setPrettyPrint(boolean prettyPrint) { this.prettyPrint = prettyPrint; } public void format(SyncML msg, OutputStream os, String charset) throws IOException { this.os = os; // Initialize the XmlWriter if (wbxml) { formatter = com.funambol.org.kxml2.wap.syncml.SyncML.createSerializer(); } else { formatter = new KXmlSerializer(); prettyPrint = true; } formatter.setOutput(os, charset); if (wbxml) { formatter.startDocument(null, null); } // Now print the message startTag(SyncML.TAG_SYNCML); SyncHdr hdr = msg.getSyncHdr(); SyncBody body = msg.getSyncBody(); if (hdr != null) { formatSyncHdr(hdr); } if (body != null) { formatSyncBody(body); } endTag(SyncML.TAG_SYNCML); formatter.endDocument(); } public void formatXmlDevInf(DevInf devInf, OutputStream os, String charset) throws IOException { this.os = os; formatter = new KXmlSerializer(); prettyPrint = true; formatter.setOutput(os, charset); formatDevInf(devInf); formatter.endDocument(); } private void formatSyncHdr(SyncHdr header) throws IOException { startTag(SyncML.TAG_SYNCHDR); VerDTD verDTD = header.getVerDTD(); if (verDTD != null) { formatSimpleTag(SyncML.TAG_VERDTD, verDTD.getValue()); } String verProto = header.getVerProto(); formatSimpleTag(SyncML.TAG_VERPROTO, verProto); String sessionId = header.getSessionID(); formatSimpleTag(SyncML.TAG_SESSIONID, sessionId); String msgId = header.getMsgID(); formatMsgId(msgId); Target target = header.getTarget(); formatTarget(target); Source source = header.getSource(); formatSource(source); String respURI = header.getRespURI(); formatSimpleTag(SyncML.TAG_RESPURI, respURI); Boolean noResp = header.getNoResp(); if (noResp != null && noResp.booleanValue() == true) { formatSimpleTag(SyncML.TAG_RESPURI, ""); } Meta meta = header.getMeta(); formatMeta(meta); Cred cred = header.getCred(); formatCred(cred); endTag(SyncML.TAG_SYNCHDR); } private void formatCred(Cred cred) throws IOException { if (cred != null) { startTag(SyncML.TAG_CRED); Meta meta = cred.getMeta(); formatMeta(meta); Data data = cred.getData(); formatData(data); endTag(SyncML.TAG_CRED); } } private void formatSourceRef(SourceRef source) throws IOException { if (source != null) { formatSimpleTag(SyncML.TAG_SOURCEREF, source.getValue()); Source s = source.getSource(); formatSource(s); } } private void formatDSMem(DSMem dsMem) throws IOException { if (dsMem != null) { startTag(SyncML.TAG_DSMEM); formatSimpleLongTag(SyncML.TAG_MAXMEM, dsMem.getMaxMem()); formatSimpleLongTag(SyncML.TAG_MAXID, dsMem.getMaxID()); endTag(SyncML.TAG_DSMEM); } } private void formatTargetRef(TargetRef target) throws IOException { if (target != null) { formatSimpleTag(SyncML.TAG_TARGETREF, target.getValue()); Target t = target.getTarget(); formatTarget(t); } } private void formatSource(Source source) throws IOException { if (source != null) { String locURI = source.getLocURI(); startTag(SyncML.TAG_SOURCE); formatSimpleTag(SyncML.TAG_LOC_URI, locURI); formatSimpleTag(SyncML.TAG_LOC_NAME, source.getLocName()); endTag(SyncML.TAG_SOURCE); } } private void formatTarget(Target target) throws IOException { if (target != null) { String locURI = target.getLocURI(); startTag(SyncML.TAG_TARGET); formatSimpleTag(SyncML.TAG_LOC_URI, locURI); formatSimpleTag(SyncML.TAG_LOC_NAME, target.getLocName()); endTag(SyncML.TAG_TARGET); } } private void formatSourceParent(SourceParent sourceParent) throws IOException { if (sourceParent != null) { String locURI = sourceParent.getLocURI(); startTag(SyncML.TAG_SOURCE_PARENT); formatSimpleTag(SyncML.TAG_LOC_URI, locURI); endTag(SyncML.TAG_SOURCE_PARENT); } } private void formatTargetParent(TargetParent targetParent) throws IOException { if (targetParent != null) { String locURI = targetParent.getLocURI(); startTag(SyncML.TAG_TARGET_PARENT); formatSimpleTag(SyncML.TAG_LOC_URI, locURI); endTag(SyncML.TAG_TARGET_PARENT); } } private void formatSyncBody(SyncBody body) throws IOException { startTag(SyncML.TAG_SYNCBODY); Vector commands = body.getCommands(); Boolean finalMsg = body.getFinalMsg(); for(int i=0;i<commands.size();++i) { Object cmd = commands.elementAt(i); if (cmd instanceof Status) { Status status = (Status)cmd; formatStatus(status); } else if (cmd instanceof Sync) { Sync sync = (Sync)cmd; formatSync(sync); } else if (cmd instanceof Results) { Results results = (Results)cmd; formatResults(results); } else if (cmd instanceof Alert) { Alert alert = (Alert)cmd; formatAlert(alert); } else if (cmd instanceof Get) { Get get = (Get)cmd; formatGet(get); } else if (cmd instanceof Put) { Put put = (Put)cmd; formatPut(put); } else if (cmd instanceof Map) { Map map = (Map)cmd; formatMap(map); } else { Log.error(TAG_LOG, "Cannot format sync body command " + cmd); } } if (finalMsg != null && finalMsg.booleanValue()) { formatSimpleTag(SyncML.TAG_FINAL, ""); } endTag(SyncML.TAG_SYNCBODY); } private void formatStatus(Status status) throws IOException { startTag(SyncML.TAG_STATUS); String cmdId = status.getCmdID(); formatSimpleTag(SyncML.TAG_CMDID, cmdId); String msgRef = status.getMsgRef(); formatSimpleTag(SyncML.TAG_MSGREF, msgRef); String cmdRef = status.getCmdRef(); formatSimpleTag(SyncML.TAG_CMDREF, cmdRef); String cmd = status.getCmd(); formatSimpleTag(SyncML.TAG_CMD, cmd); Vector targetRefs = status.getTargetRef(); if (targetRefs != null) { for(int i=0;i<targetRefs.size();++i) { TargetRef tgtRef = (TargetRef)targetRefs.elementAt(i); formatTargetRef(tgtRef); } } Vector sourceRefs = status.getSourceRef(); if (sourceRefs != null) { for(int i=0;i<sourceRefs.size();++i) { SourceRef srcRef = (SourceRef)sourceRefs.elementAt(i); formatSourceRef(srcRef); } } Cred cred = status.getCred(); formatCred(cred); Chal chal = status.getChal(); formatChal(chal); Data data = status.getData(); formatData(data); Vector items = status.getItems(); if (items != null) { for(int i=0;i<items.size();++i) { Item item = (Item)items.elementAt(i); formatItem(item); } } endTag(SyncML.TAG_STATUS); } private void formatChal(Chal chal) throws IOException { } private void formatNextNonce(NextNonce nextNonce) throws IOException { // TODO FIXME } private void formatResults(Results results) throws IOException { startTag(SyncML.TAG_RESULTS); formatSimpleTag(SyncML.TAG_CMDID, results.getCmdID()); formatSimpleTag(SyncML.TAG_MSGREF, results.getMsgRef()); formatSimpleTag(SyncML.TAG_CMDREF, results.getCmdRef()); formatMeta(results.getMeta()); Vector items = results.getItems(); for(int i=0;i<items.size();++i) { Item item = (Item)items.elementAt(i); formatItem(item); } endTag(SyncML.TAG_RESULTS); } private void formatItem(Item item) throws IOException { startTag(SyncML.TAG_ITEM); Source source = item.getSource(); formatSource(source); Target target = item.getTarget(); formatTarget(target); SourceParent sourceParent = item.getSourceParent(); formatSourceParent(sourceParent); TargetParent targetParent = item.getTargetParent(); formatTargetParent(targetParent); Meta meta = item.getMeta(); formatMeta(meta); Data data = item.getData(); formatData(data); if (item.isMoreData()) { formatSimpleTag(SyncML.TAG_MORE_DATA, ""); } endTag(SyncML.TAG_ITEM); } private void formatMap(Map map) throws IOException { if (map != null) { startTag(SyncML.TAG_MAP); String cmdId = map.getCmdID(); formatSimpleTag(SyncML.TAG_CMDID, cmdId); Target tgt = map.getTarget(); formatTarget(tgt); Source src = map.getSource(); formatSource(src); Vector mapItems = map.getMapItems(); for(int i=0;i<mapItems.size();++i) { MapItem mapItem = (MapItem)mapItems.elementAt(i); formatMapItem(mapItem); } endTag(SyncML.TAG_MAP); } } private void formatMapItem(MapItem mapItem) throws IOException { if (mapItem != null) { startTag(SyncML.TAG_MAPITEM); Source src = mapItem.getSource(); formatSource(src); Target tgt = mapItem.getTarget(); formatTarget(tgt); endTag(SyncML.TAG_MAPITEM); } } private void formatDevInf(DevInf devInf) throws IOException { if (devInf != null) { String man = devInf.getMan() != null ? devInf.getMan() : ""; String mod = devInf.getMod() != null ? devInf.getMod() : ""; String oem = devInf.getOEM() != null ? devInf.getOEM() : ""; String fwv = devInf.getFwV() != null ? devInf.getFwV() : ""; String swv = devInf.getSwV() != null ? devInf.getSwV() : ""; String hwv = devInf.getHwV() != null ? devInf.getHwV() : ""; String devID = devInf.getDevID() != null ? devInf.getDevID() : ""; String devType = devInf.getDevTyp() != null ? devInf.getDevTyp() : ""; startTagWithAttribute(SyncML.TAG_DEVINF, "xmlns", "syncml:devinf"); formatSimpleTag(SyncML.TAG_VERDTD, "1.2"); formatSimpleTag(SyncML.TAG_DEVINFMAN, man); formatSimpleTag(SyncML.TAG_DEVINFMOD, mod); formatSimpleTag(SyncML.TAG_DEVINFOEM, oem); formatSimpleTag(SyncML.TAG_DEVINFFWV, fwv); formatSimpleTag(SyncML.TAG_DEVINFSWV, swv); formatSimpleTag(SyncML.TAG_DEVINFHWV, hwv); formatSimpleTag(SyncML.TAG_DEVINFDEVID, devID); formatSimpleTag(SyncML.TAG_DEVINFDEVTYP, devType); //optional flag (if present, the server SHOULD send time in UTC form) if (devInf.isUTC()) { formatSimpleTag(SyncML.TAG_DEVINFUTC, ""); } //optional (if present, it specifies that the device supports receiving //large objects) if (devInf.isSupportLargeObjs()) { formatSimpleTag(SyncML.TAG_DEVINFLO, ""); } //optional: server MUST NOT send <NumberOfChanges> if the client has //not specified this flag if (devInf.isSupportNumberOfChanges()) { formatSimpleTag(SyncML.TAG_DEVINFNC, ""); } /* if (devInf.isSupportHierarchicalSync()) { formatSimpleTag(SyncML.TAG_DEVINFHS, ""); } */ // format all exts Vector exts = devInf.getExts(); if (exts != null) { for(int i=0;i<exts.size();++i) { Ext ext = (Ext)exts.elementAt(i); formatExt(ext); } } Vector dataStores = devInf.getDataStores(); if (dataStores != null) { for(int i=0;i<dataStores.size();++i) { DataStore ds = (DataStore)dataStores.elementAt(i); formatDataStore(ds); } } endTag(SyncML.TAG_DEVINF); } } private void formatDataStore(DataStore ds) throws IOException { if (ds != null) { startTag(SyncML.TAG_DEVINFDATASTORE); SourceRef sr = ds.getSourceRef(); formatSourceRef(sr); String displayName = ds.getDisplayName(); if(displayName != null) { formatSimpleTag(SyncML.TAG_DISPLAYNAME, displayName); } long guidSize = ds.getMaxGUIDSize(); if(guidSize > 0) { formatSimpleTag(SyncML.TAG_MAXGUIDSIZE, String.valueOf(guidSize)); } CTInfo rxPref = ds.getRxPref(); formatCTInfo(rxPref, SyncML.TAG_RXPREF); for (int i = 0; i < ds.getRxs().size(); i++) { formatCTInfo((CTInfo)ds.getRxs().elementAt(i), SyncML.TAG_RX); } CTInfo txPref = ds.getTxPref(); formatCTInfo(txPref, SyncML.TAG_TXPREF); for (int i = 0; i < ds.getTxs().size(); i++) { formatCTInfo((CTInfo)ds.getTxs().elementAt(i), SyncML.TAG_TX); } DSMem dsMem = ds.getDSMem(); if(dsMem != null) { formatDSMem(dsMem); } for (int i = 0; i < ds.getCTCaps().size(); i++) { formatCTCap((CTCap)ds.getCTCaps().elementAt(i)); } SyncCap syncCap = ds.getSyncCap(); formatSyncCap(syncCap); endTag(SyncML.TAG_DEVINFDATASTORE); } } private void formatCTInfo(CTInfo ctInfo, String sorround) throws IOException { if (ctInfo != null) { startTag(sorround); formatCTInfo(ctInfo); endTag(sorround); } } private void formatCTInfo(CTInfo ctInfo) throws IOException { if (ctInfo != null) { String type = ctInfo.getCTType(); formatSimpleTag(SyncML.TAG_CTTYPE, type); String ver = ctInfo.getVerCT(); formatSimpleTag(SyncML.TAG_VERCT, ver); } } private void formatSyncCap(SyncCap syncCap) throws IOException { if (syncCap != null) { startTag(SyncML.TAG_SYNCCAP); Vector types = syncCap.getSyncType(); for(int i=0;i<types.size();++i) { SyncType type = (SyncType)types.elementAt(i); int t = type.getType(); formatSimpleTag(SyncML.TAG_SYNCTYPE, "" + t); } endTag(SyncML.TAG_SYNCCAP); } } private void formatCTCap(CTCap ctCap) throws IOException { if (ctCap != null) { startTag(SyncML.TAG_CTCAP); formatCTInfo(ctCap.getCTInfo()); for (int i = 0; i < ctCap.getProperties().size(); i++) { formatProperty((Property)ctCap.getProperties().elementAt(i)); } endTag(SyncML.TAG_CTCAP); } } private void formatPropParam(PropParam param) throws IOException { startTag(SyncML.TAG_PROPPARAM); formatSimpleTag(SyncML.TAG_PARAMNAME, param.getParamName()); formatSimpleTag(SyncML.TAG_DATATYPE, param.getDataType()); for (int i = 0; i < param.getValEnums().size(); i++) { formatSimpleTag(SyncML.TAG_VALENUM, (String)param.getValEnums().elementAt(i)); } formatSimpleTag(SyncML.TAG_DISPLAYNAME, param.getDisplayName()); endTag(SyncML.TAG_PROPPARAM); } private void formatProperty(Property property) throws IOException { startTag(SyncML.TAG_PROPERTY); formatSimpleTag(SyncML.TAG_PROPNAME, property.getPropName()); formatSimpleTag(SyncML.TAG_DATATYPE, property.getDataType()); formatSimpleLongTag(SyncML.TAG_MAXOCCUR, property.getMaxOccur()); formatSimpleLongTag(SyncML.TAG_MAXSIZE, property.getMaxSize()); formatSimpleTag(SyncML.TAG_DATATYPE, property.getDataType()); for (int i = 0; i < property.getValEnums().size(); i++) { formatSimpleTag(SyncML.TAG_VALENUM, (String)property.getValEnums().elementAt(i)); } formatSimpleTag(SyncML.TAG_DISPLAYNAME, property.getDisplayName()); for (int i = 0; i < property.getPropParams().size(); i++) { formatPropParam((PropParam)property.getPropParams().elementAt(i)); } endTag(SyncML.TAG_PROPERTY); } private void formatData(Data data) throws IOException { if (data != null) { // We expect only of these four possibilities to have a valid value String str = data.getData(); Anchor anchor = data.getAnchor(); DevInf devInf = data.getDevInf(); byte binData[] = data.getBinData(); if (str != null) { formatSimpleTag(SyncML.TAG_DATA, str); } else if (anchor != null) { startTag(SyncML.TAG_DATA); formatAnchor(anchor); endTag(SyncML.TAG_DATA); } else if (devInf != null) { startTag(SyncML.TAG_DATA); formatDevInf(devInf); endTag(SyncML.TAG_DATA); } else if (binData != null) { startTag(SyncML.TAG_DATA); formatBinData(binData); endTag(SyncML.TAG_DATA); } } } private void formatMeta(Meta meta) throws IOException { // We only print the field supported by the parser if (meta != null) { startTag(SyncML.TAG_META); Long size = meta.getSize(); if (size != null) { formatSimpleTag(SyncML.TAG_SIZE, "" + size.longValue()); } String format = meta.getFormat(); String type = meta.getType(); formatSimpleTagWithNamespace(SyncML.TAG_FORMAT, format, METINF); formatSimpleTagWithNamespace(SyncML.TAG_TYPE, type, METINF); Anchor anchor = meta.getAnchor(); formatAnchor(anchor); NextNonce nextNonce = meta.getNextNonce(); formatNextNonce(nextNonce); Long maxMsgSize = meta.getMaxMsgSize(); if (maxMsgSize != null) { formatSimpleTag(SyncML.TAG_MAXMSGSIZE, "" + maxMsgSize.longValue()); } Long maxObjSize = meta.getMaxObjSize(); if (maxObjSize != null) { formatSimpleTag(SyncML.TAG_MAXOBJSIZE, "" + maxObjSize.longValue()); } String version = meta.getVersion(); if (version != null) { formatSimpleTag(SyncML.TAG_VERSION, version); } endTag(SyncML.TAG_META); } } private void formatAnchor(Anchor anchor) throws IOException { if (anchor != null) { String next = anchor.getNext(); String last = anchor.getLast(); startTagWithAttribute(SyncML.TAG_ANCHOR, "xmlns", METINF); formatSimpleTag(SyncML.TAG_NEXT, next); formatSimpleTag(SyncML.TAG_LAST, last); endTag(SyncML.TAG_ANCHOR); } } private void formatBinData(byte binData[]) throws IOException { if (binData != null) { if (formatter instanceof WbxmlSerializer) { if (Log.isLoggable(Log.TRACE)) { Log.trace(TAG_LOG, "Formatting binary data: " + binData.length); } WbxmlSerializer wbxmlFormatter = (WbxmlSerializer)formatter; wbxmlFormatter.writeWapExtension(Wbxml.OPAQUE, binData); } else { if (prettyPrint) { String textData = null; if (Log.getLogLevel() >= Log.DEBUG) { textData = new String(binData); // Check if this string can be printed if (!isPrintableString(textData)) { textData = null; } } if (textData == null) { formatter.text("******* binary data ********"); } else { formatter.text(textData); } } else { throw new IOException("Cannot write binary data to XML"); } } } } private void formatSync(Sync sync) throws IOException { if (sync != null) { startTag(SyncML.TAG_SYNC); String cmdId = sync.getCmdID(); formatSimpleTag(SyncML.TAG_CMDID, cmdId); boolean noResp = hasNoResp(sync.getNoResp()); if (noResp) { formatSimpleTag(SyncML.TAG_NORESP, ""); } Cred cred = sync.getCred(); formatCred(cred); Target target = sync.getTarget(); formatTarget(target); Source source = sync.getSource(); formatSource(source); Meta meta = sync.getMeta(); formatMeta(meta); Long numChanges = sync.getNumberOfChanges(); if (numChanges != null) { formatSimpleTag(SyncML.TAG_NUMBEROFCHANGES, ""+numChanges.longValue()); } Vector commands = sync.getCommands(); for(int i=0;i<commands.size();++i) { SyncMLCommand command = (SyncMLCommand) commands.elementAt(i); formatCommand(command); } endTag(SyncML.TAG_SYNC); } } private void formatCommand(SyncMLCommand command) throws IOException { if (command != null) { startTag(command.getName()); String cmdId = command.getCmdId(); formatSimpleTag(SyncML.TAG_CMDID, cmdId); Meta meta = command.getMeta(); formatMeta(meta); Vector items = command.getItems(); for(int i=0;i<items.size();++i) { Item item = (Item)items.elementAt(i); formatItem(item); } endTag(command.getName()); } } private void formatPut(Put put) throws IOException { if (put != null) { startTag(SyncML.TAG_PUT); formatItemizedCommand(put); String lang = put.getLang(); formatSimpleTag(SyncML.TAG_LANG, lang); endTag(SyncML.TAG_PUT); } } private void formatGet(Get get) throws IOException { if (get != null) { startTag(SyncML.TAG_GET); formatItemizedCommand(get); String lang = get.getLang(); formatSimpleTag(SyncML.TAG_LANG, lang); endTag(SyncML.TAG_GET); } } private void formatItemizedCommand(ItemizedCommand icommand) throws IOException { if (icommand != null) { String cmdId = icommand.getCmdID(); formatSimpleTag(SyncML.TAG_CMDID, cmdId); boolean noResp = hasNoResp(icommand.getNoResp()); if (noResp) { formatSimpleTag(SyncML.TAG_NORESP, ""); } Cred cred = icommand.getCred(); formatCred(cred); Meta meta = icommand.getMeta(); formatMeta(meta); Vector items = icommand.getItems(); for(int i=0;i<items.size();++i) { Item item = (Item)items.elementAt(i); formatItem(item); } } } private void formatAlert(Alert alert) throws IOException { if (alert != null) { startTag(SyncML.TAG_ALERT); formatItemizedCommand(alert); formatSimpleTag(SyncML.TAG_DATA, "" + alert.getData()); endTag(SyncML.TAG_ALERT); } } private void formatExt(Ext ext) throws IOException { if (ext != null) { formatter.startTag(null, SyncML.TAG_EXT); String xnam = ext.getXNam(); Vector xval = ext.getXVal(); if (xnam != null) { formatSimpleTag(SyncML.TAG_XNAM, xnam); } if (xval != null) { for(int i=0;i<xval.size();++i) { String v = (String)xval.elementAt(i); formatSimpleTag(SyncML.TAG_XVAL, v); } } formatter.endTag(null, SyncML.TAG_EXT); } } private void formatSimpleTag(String tagName, String value) throws IOException { formatSimpleTagWithNamespace(tagName, value, null); } private void formatSimpleLongTag(String tagName, long value) throws IOException { if(value > 0) { formatSimpleTagWithNamespace(tagName, Long.toString(value), null); } } // Unfortunately some servers exhibit bugs at parsing CDATA in // some fields (e.g. MsgID), so in some cases we do the escaping private void formatMsgId(String msgId) throws IOException { if (msgId != null) { formatter.startTag(null, SyncML.TAG_MSGID); formatter.text(msgId); formatter.endTag(null, SyncML.TAG_MSGID); if (prettyPrint) { println(); } } } private void formatSimpleTagWithNamespace(String tagName, String value, String namespace) throws IOException { if (value != null) { formatter.startTag(null, tagName); if (namespace != null) { formatter.attribute(null, "xmlns", namespace); } // For performance reason we always use CDATA because it does // not require escaping. kxml2 is really ineffecient at escaping // text, so we try to avoid it as much as possible. if (value.length() == 0) { formatter.text(""); } else { formatter.text(value); //formatter.cdsect(value); } formatter.endTag(null, tagName); if (prettyPrint) { println(); } } } private void println() throws IOException { formatter.text("\n"); } private void startTag(String tagName) throws IOException { formatter.startTag(null, tagName); if (prettyPrint) { println(); } } private void endTag(String tagName) throws IOException { formatter.endTag(null, tagName); if (prettyPrint) { println(); } } private void startTagWithAttribute(String tagName, String attrName, String attrValue) throws IOException { formatter.startTag(null, tagName); formatter.attribute(null, attrName, attrValue); if (prettyPrint) { println(); } } private boolean hasNoResp(Boolean nr) { if (nr != null && nr.booleanValue()) { return true; } else { return false; } } private boolean isPrintableString(String str) { return true; } }