📄 syncmanager.java
字号:
String cmdTag = cmd.getName();
if (cmdTag.equals(SyncML.TAG_ADD)) {
item = this.getItem(item.STATE_NEW, cmd.getType(), xmlItem, formatList);
// Save the key sent by server, it will be replaced by the SyncSource
// with the local UID.
guid = new String(item.getKey()); // Duplicate to avoid leaks!!
// Preliminary check: don't pass a null item to the SyncSource
// for add
if (item.getContent() != null) {
status = source.addItem(item);
if (SyncMLStatus.isSuccess(status)) {
listener.itemReceived(item.getClientRepresentation());
}
} else {
status = SyncMLStatus.GENERIC_ERROR;
}
if (SyncMLStatus.isSuccess(status)) {
mappings.put(new String(item.getKey()), guid); // Avoid leaks!!
}
} else if (cmdTag.equals(SyncML.TAG_REPLACE)) {
item = this.getItem(item.STATE_UPDATED, cmd.getType(), xmlItem, formatList);
// Preliminary check: don't pass a null item to the SyncSource
// for update
if (item.getContent() != null) {
status = source.updateItem(item);
if (SyncMLStatus.isSuccess(status)) {
listener.itemUpdated(item.getKey(),
item.getClientRepresentation());
}
} else {
status = SyncMLStatus.GENERIC_ERROR;
}
} else if (cmdTag.equals(SyncML.TAG_DELETE)) {
item = this.getItem(item.STATE_DELETED, cmd.getType(), xmlItem, formatList);
status = this.source.deleteItem(item.getKey());
if (SyncMLStatus.isSuccess(status)) {
listener.itemDeleted(item.getKey());
}
} else {
Log.error("[processItem] Invalid command: " + cmd.toString());
}
// Init the status object
SyncMLStatus ret = new SyncMLStatus();
ret.setCmd(cmdTag);
ret.setCmdRef(cmd.getCmdId());
// Save the source ref if present (ADD), otherwise the target ref (UPD & DEL)
if (guid != null) {
ret.setSrcRef(guid);
} else {
ret.setTgtRef(item.getKey());
}
ret.setStatus(status);
return ret;
}
/**
* Processes a modification command received from server,
* returning the command parts in an Hashtable
*
* @param msgRef The messageId tag of the message containing this command
* @param cmdName the command name
* @param command the body of the command
*
* @return the number of modifications made
*
* @throws SyncException if the command parsing failed
*
*/
private int processCommand(ChunkedString msgRef, String cmdName, ChunkedString command)
throws SyncException {
ChunkedString cmdId = null;
int i = 0;
// Get command Id
try {
cmdId = XmlUtil.getTagValue(command, SyncML.TAG_CMDID);
} catch (XmlException e) {
Log.error("[processCommand] Invalid command Id from server: " + command);
e.printStackTrace();
throw new SyncException(
SyncException.SERVER_ERROR,
"Invalid command from server.");
}
SyncMLCommand cmd = new SyncMLCommand(cmdName, cmdId.toString());
try {
// Get the type of the items for this command, if present
// otherwise use the type defined for this source.
int pos = XmlUtil.getTag(command, SyncML.TAG_TYPE);
String itemType = null;
if (pos != -1) {
try {
itemType = XmlUtil.getTagValue(command, SyncML.TAG_TYPE).toString();
//int begin = command.indexOf(">", pos);
//int end = command.indexOf("</"++">", begin);
//if(begin != -1 && end != -1) {
// itemType = command.substring(begin+1, end).toString();
//}
} catch (XmlException xe) {
xe.printStackTrace();
Log.error("Error parsing item type, using default for source.");
}
}
// Set the command type or use the source one
if (itemType != null) {
cmd.setType(itemType);
} else {
cmd.setType(source.getType());
}
// Process format tag (encryption and encoding)
String[] formatList = this.processFormat(command);
Vector itemTags = XmlUtil.getTagValues(command, SyncML.TAG_ITEM);
int len = itemTags.size();
// Process items
SyncMLStatus status = null;
for (i = 0; i < len; i++) {
status = this.processSyncItem(cmd, (ChunkedString) itemTags.elementAt(i), formatList);
status.setMsgRef(msgRef.toString());
statusList.addElement(status);
}
} catch (XmlException xe) {
xe.printStackTrace();
Log.error("[processCommand] Parse error: " + xe.toString());
throw new SyncException(
SyncException.SERVER_ERROR,
"Error processing command:" + cmdName + " in message " + msgRef);
}
return i;
}
/**
* Processes the modifications from the received response from server
*
* @param modifications The modification message from server
* @return true if a response message is required, false otherwise
* @throws SyncException
*/
private boolean processModifications(ChunkedString modifications)
throws SyncException {
boolean ret = false;
ChunkedString msgId = null;
ChunkedString bodyTag = null;
try {
// Check the SyncML tag
if (XmlUtil.getTag(modifications, SyncML.TAG_SYNCML) == -1) {
Log.error("Invalid message from server.");
throw new SyncException(
SyncException.SERVER_ERROR,
"Invalid message from server.");
}
// Process header
ChunkedString syncHdr = XmlUtil.getTagValue(modifications,
SyncML.TAG_SYNCHDR);
// Get message id
msgId = XmlUtil.getTagValue(syncHdr, SyncML.TAG_MSGID);
// Get message body
bodyTag = XmlUtil.getTagValue(modifications, SyncML.TAG_SYNCBODY);
} catch (XmlException e) {
Log.error("[processModification] error parsing message: " + e.toString());
throw new SyncException(
SyncException.SERVER_ERROR,
"Error parsing message: " + e.getMessage());
}
// Process body
Vector cmdTags = null;
Vector xmlBody = new Vector(1);
xmlBody.addElement(bodyTag);
// Ignore incoming modifications for one way from client modes
if (alertCode != SyncML.ALERT_CODE_ONE_WAY_FROM_CLIENT &&
alertCode != SyncML.ALERT_CODE_REFRESH_FROM_CLIENT) {
try {
// If the server sends a <Sync> tag, the message contains
// modifications, otherwise it contains only status.
if (XmlUtil.getTag(bodyTag, SyncML.TAG_SYNC) != - 1) {
ret = true;
String[] cmdNames = {SyncML.TAG_ADD,
SyncML.TAG_REPLACE,
SyncML.TAG_DELETE
};
processSyncCommand(msgId, bodyTag);
bodyTag = null;
// Process commands, one kind at a time, in the order
// defined above
for (int c = 0; c < cmdNames.length; c++) {
int count = 0;
Log.debug("[processModification] processing " + cmdNames[c] + " commands");
cmdTags = XmlUtil.getTagValues(xmlBody, cmdNames[c]);
for (int i = 0, l = cmdTags.size(); i < l; i++) {
ChunkedString command = (ChunkedString) cmdTags.elementAt(i);
count += processCommand(msgId, cmdNames[c], command);
command = null;
}
cmdTags = null;
Log.info(cmdNames[c] + ": " + count + " items processed");
}
}
} catch (XmlException e) {
e.printStackTrace();
Log.error("[processModification] error parsing command: " + e.toString());
}
}
try {
// Process status commands
cmdTags = XmlUtil.getTagValues(xmlBody, SyncML.TAG_STATUS);
SyncMLStatus status = null;
for (int i = 0, l = cmdTags.size(); i < l; i++) {
status = SyncMLStatus.parse((ChunkedString) cmdTags.elementAt(i));
if (status != null) {
String cmd = status.getCmd();
Log.debug("[processModification] processing Status for <" + cmd + "> command.");
// Check status to SyncHdr and Sync
if (cmd.equals(SyncML.TAG_SYNCHDR) || cmd.equals(SyncML.TAG_SYNC)) {
if (status.getStatus() == 506) {
String msg = "Server responded " + status.getStatus() + " to command " + cmd + " [" + status.getStatusDataMessage() + "]"; //506
Log.error(msg);
throw new SyncException(SyncException.BACKEND_ERROR, msg);
} else if (status.getStatus() == 511) {
String msg = "Server responded " + status.getStatus() + " to command " + cmd + " [" + status.getStatusDataMessage() + "]"; //511
Log.error(msg);
throw new SyncException(SyncException.BACKEND_AUTH_ERROR, msg);
}else if (status.getStatus() < 200 || status.getStatus() >= 300) {
String msg = "Server responded " + status.getStatus() + " to command " + cmd + " [" + status.getStatusDataMessage() + "]"; //XXX
Log.error(msg);
throw new SyncException(SyncException.SERVER_ERROR, msg);
}
} else {
// Otherwise, pass it to the source
String[] items = status.getItemKeys();
int code = status.getStatus();
// Check if it's a multi-item response
if (items != null) {
for (int j = 0, n = items.length; j < n; j++) {
source.setItemStatus(items[j], code);
// Notify the listener
listener.itemUpdated(items[j]);
}
} else {
source.setItemStatus(status.getRef(), code);
// Notify the listener
listener.itemUpdated(status.getRef());
}
}
status = null;
} else {
Log.error("[processModification] error in Status command.");
}
}
} catch (XmlException e) {
e.printStackTrace();
Log.error("[processModification] error parsing status: " + e.toString());
}
modifications = null;
return ret;
}
/**
* Prepares the modification message in SyncML.
*
* @return the formatted message
*/
private String prepareModificationMessage() throws SyncException {
StringBuffer modMsg = new StringBuffer("<SyncML>");
// Meta
String meta = "<Meta><MaxMsgSize>" + maxMsgSize + "</MaxMsgSize></Meta>\n";
// Sync header
String syncHdr = prepareSyncHeader(sessionID, getNextMsgID(),
deviceId, serverUrl,
meta);
modMsg.append(syncHdr);
// Sync Body
modMsg.append("<SyncBody>\n");
// Status to the alert command
// This is used to address the correct MsgIdRef on the outgoing message
int msgIdRef = msgID - 1;
modMsg.append("<Status>\n").append("<CmdID>").append(resetCmdID()).append("</CmdID>\n").append("<MsgRef>" + msgIdRef + "</MsgRef><CmdRef>0</CmdRef>\n") //fixMe
.append("<Cmd>SyncHdr</Cmd>\n").append("<TargetRef>").append(deviceId).append("</TargetRef>\n").append("<SourceRef>").append(serverUrl).append("</SourceRef>\n").append("<Data>200</Data>\n</Status>\n");
// Add the status to the Alert message
// FIXME: now it checks msgId, but this test is not very smart
// should use SyncMLStatus for this too? (anchor must be added)
if (msgID == 2) {
modMsg.append("<Status>\n").append("<CmdID>").append(getNextCmdID()).append("</CmdID>\n").append("<MsgRef>1</MsgRef><CmdRef>1</CmdRef><Cmd>Alert</Cmd>\n").append("<TargetRef>").append(source.getSourceUri()).append("</TargetRef>\n").append("<SourceRef>").append(source.getSourceUri()).append("</SourceRef>\n").append("<Data>200</Data>\n").append("<Item>\n").append("<Data>\n").append("<Anchor xmlns=\"syncml:metinf\"><Next>").append(source.getNextAnchor()).append("</Next></Anchor>\n").append("</Data>\n").append("</Item>\n").append("</Status>\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -