/* | |
* ======== processCommand ======== | |
* Accepts a string command line and services the request. | |
*/ | |
function processCommand(input) { | |
var Model = xdc.useModule('xdc.rov.Model'); | |
var Program = xdc.useModule('xdc.rov.Program'); | |
/* Verify Model has been initialized. */ | |
if (!Model.$private.initialized) { | |
return("<Exception>ROV Model not initialized</Exception>"); | |
} | |
try { | |
var result = pCmd(input); | |
} | |
catch (e) { | |
var exception = Program.exToString(e); | |
Program.debugPrint("rov/server/main.xs caught exception while " + | |
"processing command: " + exception); | |
var result = "<Exception>" + xmlQuote(exception) + "</Exception>"; | |
} | |
return (result); | |
} | |
function pCmd(input) | |
{ | |
var Program = xdc.useModule('xdc.rov.Program'); | |
Program.debugPrint("Model - Processing command " + input); | |
/* Clear Cache */ | |
if (input == "cc") { | |
Program.debugPrint("Clearing server cache..."); | |
Program.resetMods(); | |
/* | |
* Server writes out an empty string to acknowledge that the | |
* cache has been cleared. | |
*/ | |
return (""); | |
} | |
/* List modules */ | |
else if (input == "lm") { | |
return(listModules()); | |
} | |
/* | |
* Retrieve Module (m is 109 in Java) | |
* | |
* Module requests have the form: | |
* m <module name> <tab name> | |
* m ti.sysbios.knl.Task Detailed | |
* | |
* The tab name comes last so that it may contain spaces. | |
*/ | |
else if (input.charAt(0) == 'm') { | |
Program.debugPrint("RovServer received request: " + input); | |
var modName = input.substring(2); | |
/* Find the index of the space after the module name */ | |
var index = input.indexOf(' ', 3); | |
modName = input.substring(2, index); | |
var tabName = input.substring(index + 1, input.length); | |
return (retrieveView(modName, tabName)); | |
} | |
/* Unrecognized command */ | |
else { | |
return ("<Exception>Unrecognized command</Exception>"); | |
} | |
} | |
/* | |
* ======== listModules ======== | |
* | |
*/ | |
function listModules() | |
{ | |
var Model = xdc.useModule('xdc.rov.Model'); | |
Program.debugPrint("Listing modules..."); | |
/* Get the package hierarchy as a js object */ | |
var moduleList = Model.getModuleList(); | |
/* Convert the package hierarchy to an XML object */ | |
var sb = new java.lang.StringBuilder(); | |
sb.append("<ModuleList>\n"); | |
moduleListToXML(sb, moduleList, " "); | |
sb.append("</ModuleList>\n"); | |
Program.debugPrint("Module list = \n" + sb.toString()); | |
return (sb.toString()); | |
} | |
/* | |
* ======== retrieveView ======== | |
* | |
*/ | |
function retrieveView(modName, tabName) | |
{ | |
Program.debugPrint("Retrieving: tab " + tabName + | |
" for module " + modName); | |
var viewType = Program.getViewType(modName, tabName); | |
var ViewInfo = xdc.useModule('xdc.rov.ViewInfo'); | |
switch (String(viewType)) { | |
case String(ViewInfo.MODULE): | |
view = retrieveModuleView(modName, tabName); | |
break; | |
case String(ViewInfo.INSTANCE): | |
view = retrieveInstanceView(modName, tabName); | |
break; | |
case String(ViewInfo.INSTANCE_DATA): | |
view = retrieveInstanceDataView(modName, tabName); | |
break; | |
case String(ViewInfo.MODULE_DATA): | |
view = retrieveModuleDataView(modName, tabName); | |
break; | |
case String(ViewInfo.RAW): | |
view = retrieveRawView(modName); | |
break; | |
default: | |
throw (new Error("Undefined view type: " + viewType)); | |
break; | |
} | |
/* Check abort flag before returning. */ | |
var Model = xdc.useModule('xdc.rov.Model'); | |
if (Model.getICallBackInst().getAbortFlag()) { | |
return("abort"); | |
} | |
return (view.toString()); | |
} | |
/* | |
* ======== moduleListToXML ======== | |
* This function turns the module list into an XML structure. It does not use | |
* the JavaScript XML type to build the structure--it turns out it's much | |
* quicker / more efficient to simply build the structure as a String using a | |
* StringBuilder. | |
*/ | |
function moduleListToXML(sb, elem, pad) { | |
/* | |
* For each package, display subpackages first, followed by any modules | |
* in the package. | |
*/ | |
var modules = new Array(); | |
for (var i = 0; i < elem.children.length; i++) { | |
/* Handle the modules after adding all the packages. */ | |
if (elem.children[i].isModule) { | |
modules[modules.length] = elem.children[i]; | |
} | |
else { | |
var pkg = elem.children[i]; | |
var folder = pkg.name.substring(pkg.name.lastIndexOf('.') + 1); | |
sb.append(pad + "<" + folder + " type=\"package\">\n"); | |
moduleListToXML(sb, pkg, pad + " "); | |
sb.append(pad + "</" + folder + ">\n"); | |
} | |
} | |
/* Handle the modules */ | |
for (var i = 0; i < modules.length; i++) { | |
var mod = modules[i]; | |
sb.append(pad + "<" + mod.name + " type=\"module\">\n"); | |
for (var j = 0; j < mod.tabs.length; j++) { | |
sb.append(pad + " <view type=\"" + mod.tabs[j].type + "\">" + encode(mod.tabs[j].name) + "</view>\n"); | |
} | |
sb.append(pad + "</" + mod.name + ">\n"); | |
} | |
} | |
/* | |
* ======== retrieveModuleView ======== | |
* Retrieve the specified module-type view. Call Program.getViewType to | |
* determine which Model.retrieve* API to call. | |
* Returns an XML formatted string representing the view. | |
*/ | |
function retrieveModuleView(modName, tabName) | |
{ | |
var msgOk = "ROV detected errors in scan of"; | |
try { | |
Program.scanModuleView(modName, tabName); | |
} | |
catch (e) { | |
if (e.message == "abort") { | |
return ("abort"); | |
} | |
/* | |
* Program.scanModuleView will intentionally throw exceptions to | |
* force user to handle them. | |
* If this is that type of excpetion, continue on. | |
* Otherwise, report the exception directly instead of continuing. | |
*/ | |
else if (!e.message.substring(0, msgOk.length).equals(msgOk)) { | |
throw e; | |
} | |
} | |
/* Get the view manually in case it threw an exception. */ | |
var modDesc = Program.getModuleDesc(modName); | |
var modView = modDesc.viewMap[tabName]; | |
/* | |
* The final result has the form: | |
* <Tab name="Module"> <-- tab name | |
* <ti.sysbios.knl.Task> <-- mod name | |
* <ti.sysbios.knl.Task.Module_View> <-- mod view | |
* <schedulerLocked> | |
*/ | |
var viewXML = viewToXML(modView, modDesc.error); | |
var modRoot = new XML('<' + modName + '/>'); | |
modRoot[viewXML.name()] = viewXML; | |
var tabRoot = new XML('<Tab name="' + encode(tabName) + '"/>'); | |
tabRoot[modName] = modRoot; | |
return (tabRoot); | |
} | |
/* | |
* ======== retrieveInstanceView ======== | |
* Retrieve the specified instance-type view. Call Program.getViewType to | |
* determine which Model.retrieve* API to call. | |
* Returns an XML formatted string representing the view. | |
*/ | |
function retrieveInstanceView(modName, tabName) | |
{ | |
var msgOk = "ROV detected errors in scan of"; | |
try { | |
Program.scanInstanceView(modName, tabName); | |
} | |
catch (e) { | |
if (e.message == "abort") { | |
return ("abort"); | |
} | |
/* | |
* Program.scanInstanceView will intentionally throw exceptions to | |
* force user to handle them. | |
* If this is that type of excpetion, continue on. | |
* Otherwise, report the exception directly instead of continuing. | |
*/ | |
else if (!e.message.substring(0, msgOk.length).equals(msgOk)) { | |
throw e; | |
} | |
} | |
var mod = Program.getModuleDesc(modName); | |
var root = new XML('<' + modName + '/>'); | |
var count = 0; | |
/* Get the instance views, add them to the XML output */ | |
Program.debugPrint("mod.instances.length = " + mod.instances.length); | |
/* Convert each instance to XML. */ | |
for (var i in mod.instances) { | |
var view = mod.instances[i].viewMap[tabName]; | |
Program.debugPrint ("view = " + view); | |
var viewXml = viewToXML(view, mod.instances[i].error); | |
/* The first time around... */ | |
if (i == 0) { | |
root[viewXml.name()] = viewXml; | |
} | |
root[viewXml.name()][i] = viewXml; | |
} | |
/* Add the module root underneath the tab name root */ | |
var tabRoot = new XML('<Tab name="' + tabName + '"/>'); | |
tabRoot[modName] = root; | |
return (tabRoot); | |
} | |
/* | |
* ======== retrieveInstanceDataView ======== | |
* Retrieve the specified instance-data-type view. Call Program.getViewType to | |
* determine which Model.retrieve* API to call. | |
* Returns an XML formatted string representing the view. | |
*/ | |
function retrieveInstanceDataView(modName, tabName) | |
{ | |
var e; | |
try { | |
var dataArr = Program.scanInstanceDataView(modName, tabName); | |
} | |
catch (e) { | |
if (e.message == "abort") { | |
return ("abort"); | |
} | |
else { | |
var exception = Program.exToString(e); | |
Program.debugPrint("Caught exception in ROV Server: " + exception); | |
} | |
} | |
var rawView = new java.lang.StringBuilder(); | |
rawView.append('<Tab name="' + tabName + '" type="data">\n'); | |
rawView.append(' <' + modName + '>\n'); | |
for each (var instView in dataArr) { | |
rawView.append(' <' + instView.$type + '>\n'); // xdc.rov.Program.DataView | |
rawView.append(' <label>' + instView.label + '</label>\n'); | |
rawView.append(' <elements>\n'); | |
/* Add each data element */ | |
for each (var elem in instView.elements) { | |
rawView.append(viewToXML(elem, null).toString()); | |
} | |
rawView.append(' </elements>\n'); | |
rawView.append(' </' + instView.$type + '>\n'); // xdc.rov.Program.DataView | |
} | |
rawView.append(' </' + modName + '>\n'); | |
rawView.append('</Tab>\n'); | |
return (String(rawView)); | |
} | |
/* | |
* ======== retrieveModuleDataView ======== | |
* Retrieve the specified module-data-type view. Call Program.getViewType | |
* to determine which Model.retrieve* API to call. | |
* Returns an XML formatted string representing the view. | |
*/ | |
function retrieveModuleDataView(modName, tabName) | |
{ | |
var e; | |
try { | |
var dataView = Program.scanModuleDataView(modName, tabName); | |
} | |
catch (e) { | |
if (e.message == "abort") { | |
return ("abort"); | |
} | |
else { | |
var exception = Program.exToString(e); | |
Program.debugPrint("Caught exception in ROV Server: " + exception); | |
/* Re-throw the exception so that the user sees it. */ | |
throw (e); | |
} | |
} | |
var xmlView = new java.lang.StringBuilder(); | |
xmlView.append('<Tab name="' + tabName + '" type="module_data">\n'); | |
xmlView.append('<' + modName + '>\n'); | |
/* Add each data element */ | |
for each (var elem in dataView.elements) { | |
xmlView.append(viewToXML(elem, null).toString() + "\n"); | |
} | |
xmlView.append('</' + modName + '>\n'); | |
xmlView.append('</Tab>\n'); | |
return (String(xmlView)); | |
} | |
/* | |
* ======== viewToXML ======== | |
* Converts a single view structure to XML. This function is leveraged for | |
* all of the view types except for the Raw tab. | |
*/ | |
function viewToXML(view, error) { | |
var viewXml = new XML('<' + view.$type + '/>'); | |
/* | |
* Address field is added explicitly because it doesn't show up in | |
* the for/in loop. | |
*/ | |
if ('address' in view) { | |
viewXml["address"] = view.address; | |
} | |
if (error) { | |
viewXml["address"].@error = encode(error); | |
} | |
for (var p in view) { | |
/* If the status is undefined, don't include this field. */ | |
if (view.$status[p] === undefined) { | |
continue; | |
} | |
/* If the field is an array... */ | |
if ((view[p]) && (view[p].$category == 'Vector')) { | |
var array = new XML('<' + p + '/>'); | |
/* | |
* Create child elements for each array element, | |
* formatted like array-0, array-1, etc. | |
*/ | |
for (var i = 0; i < view[p].length; i++) { | |
var index = p + "-" + i; | |
array[index] = encode(view[p][i]); | |
} | |
viewXml[p] = array; | |
} | |
/* If the field didn't get filled in, display an empty box */ | |
else if (view[p] == undefined) { | |
viewXml[p] = ""; | |
} | |
/* If this is just a normal field. */ | |
else { | |
viewXml[p] = encode(view[p]); | |
} | |
/* If the status is non-null, there's an error to report. */ | |
if (view.$status[p] != null) { | |
viewXml[p].@error = encode(view.$status[p]); | |
} | |
} | |
return (viewXml); | |
} | |
/* | |
* ======== encode ======== | |
* Encodes the given string to make it safe for XML. | |
*/ | |
function encode(str) { | |
return(java.net.URLEncoder.encode(str, 'UTF-8')); | |
} | |
/* | |
* ======== retrieveRawView ======== | |
* The raw tab is handled specially because of it's more generic nature and | |
* the complexity of displaying the configuration object. | |
* All of the functions that follow are to support the raw tab. | |
*/ | |
function retrieveRawView(modName) | |
{ | |
var rawObj = Program.scanRawView(modName); | |
var rawView = new java.lang.StringBuilder(); | |
rawView.append('<Tab name="Raw">\n'); | |
rawView.append(' <' + modName + '>\n'); | |
Program.debugPrint("Creating raw view XML"); | |
/* Add the module state */ | |
if (rawObj.modState != null) { | |
var modView = rawToXML(rawObj.modState, "Module State", " "); | |
rawView.append(modView); | |
} | |
Program.debugPrint("Creating raw view XML for instances"); | |
/* Add the instance states */ | |
rawView.append(' <property name="Instance States">\n'); | |
for each (var obj in rawObj.instStates) { | |
var elemName = Program.getShortName(obj.$label); | |
if (elemName == "") { | |
elemName = String(obj.$addr); | |
} | |
var instView = rawToXML(obj, elemName, " "); | |
rawView.append(instView); | |
} | |
rawView.append(' </property>\n'); | |
/* Add the module config info */ | |
/* This will take some work. Can't have '$' in XML name. */ | |
var cfgView = rawToXML(rawObj.modCfg, "Configuration", " "); | |
rawView.append(cfgView); | |
rawView.append(' </' + modName + '>\n'); | |
rawView.append('</Tab>\n'); | |
return (String(rawView)); | |
} | |
/* | |
* ======== rawToXML ======== | |
*/ | |
function rawToXML(obj, elemName, pad) | |
{ | |
var sb = new java.lang.StringBuilder(); | |
sb.append(pad + '<property name="' + elemName + '">\n'); | |
xmlStruct(sb, obj, pad + " ", 0); | |
sb.append(pad + '</property>\n'); | |
return String(sb); | |
} | |
/* | |
* ======== xmlStruct ======== | |
* Convert a structure to XML using a string builder. | |
*/ | |
function xmlStruct(sb, obj, pad, level) | |
{ | |
if ((level != undefined) && (level != -1)) { | |
level++; | |
} | |
for (var field in obj) { | |
xmlField(sb, field, obj[field], pad, level); | |
} | |
} | |
/* | |
* ======== xmlField ======== | |
* Convert the field of a structure into XML using a string builder. | |
*/ | |
function xmlField(sb, field, value, pad, level) | |
{ | |
/* If the field is an object... */ | |
if (value && typeof value == 'object') { | |
/* If this is an address or an enum (an Addr or EnumVal object)... */ | |
if (('$category' in value) && | |
((value.$category == 'Addr') || (value.$category == 'EnumVal'))) { | |
appendProperty(sb, pad, field, String(value)); | |
} | |
/* Otherwise it's just another structure... */ | |
else { | |
if (level == 5) { | |
appendProperty(sb, pad, field, "ROV reached max depth (5)"); | |
} | |
else { | |
sb.append(pad + '<property name="' + encode(field) + '">\n'); | |
xmlStruct(sb, value, pad + " ", level); | |
sb.append(pad + '</property>\n'); | |
} | |
} | |
} | |
/* If the field is just a scalar value... */ | |
else { | |
appendProperty(sb, pad, field, String(value)); | |
} | |
} | |
/* | |
* ======== xmlQuote ======== | |
* Quote special characters in a string for use in an XML document. | |
*/ | |
function xmlQuote(str) { | |
str = str.replace(/&/g, "&"); | |
str = str.replace(/</g, "<"); | |
str = str.replace(/>/g, ">"); | |
str = str.replace(/'/g, "'"); | |
str = str.replace(/"/g, """); | |
return str; | |
} | |
function appendProperty(sb, pad, field, value) | |
{ | |
//sb.append(pad + '<' + field + '>' + String(value) + '</' + field + '>\n'); | |
sb.append(pad + '<property name="' + encode(field) + '">' + encode(value) + '</property>\n'); | |
} |