| /* --COPYRIGHT--,EPL |
| * Copyright (c) 2008 Texas Instruments and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Texas Instruments - initial implementation |
| * |
| * --/COPYRIGHT--*/ |
| /* |
| * ======== MetaData.java ======== |
| */ |
| package xdc.rta; |
| |
| import java.util.HashMap; |
| import java.util.Vector; |
| import java.util.Set; |
| |
| import java.io.File; |
| import java.io.IOException; |
| |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.DocumentBuilder; |
| |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NodeList; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.Document; |
| |
| import xdc.rov.TargetType; |
| |
| /* |
| * ======== MetaData ======== |
| * Wrapper for the RTA XML file generated for every RTSC application. |
| * |
| * The RTA XML file contains information about the application's target, |
| * loggers, modules, and events. The MetaData class provides APIs for |
| * accessing this information. |
| * |
| * The MetaData object must be initialized using one of the parse APIs. |
| */ |
| public class MetaData implements IEventMetaData |
| { |
| /* Target information */ |
| private int argSize = -1; // Target arg size in bytes |
| private int bitsPerChar = -1; |
| private int eventSize = -1; |
| private String targetName = ""; |
| private TargetType.Endianess endian; |
| |
| /* Modules */ |
| private HashMap<Integer, String> modIdToName = null; |
| private HashMap<String, Integer> modNameToId = null; |
| private HashMap<String, DiagConfig> modNameToDiags = null; |
| private HashMap<String, String> modNameToLogger = null; |
| |
| /* Events */ |
| private HashMap<Integer, String> evtIdToName = null; |
| private HashMap<String, Integer> evtNameToId = null; |
| private HashMap<Integer, String> evtIdToMsg = null; |
| |
| /* Loggers */ |
| private String[] loggerNames = null; |
| private HashMap<String, Integer> loggerToId = null; |
| private Vector<Logger> loggers = null; |
| |
| /* Object file reader for looking up Log_print strings */ |
| private String binaryParserClass = ""; |
| private IOFReader ofReader = null; |
| |
| /* Class names of data and control transports to use for this app. */ |
| private String dataTransportClassName = ""; |
| private String controlTransportClassName = ""; |
| |
| /*! |
| * ======== Logger ======== |
| * Contains the properties of a target logger instance. |
| */ |
| public class Logger { |
| public int id; |
| |
| /* A name to associate with this logger instance. */ |
| public String name; |
| |
| /* The name of the logger module. */ |
| public String type; |
| |
| public Node metaArgs; |
| |
| /* The list of modules which log to this logger. */ |
| public Vector<String> modules; |
| |
| public Logger() |
| { |
| modules = new Vector<String>(); |
| } |
| } |
| |
| /* |
| * ======== getBitsPerChar ======== |
| * Returns the MAU size for this target in bits. |
| */ |
| public int getBitsPerChar() |
| { |
| return (this.bitsPerChar); |
| } |
| |
| /* |
| * ======== getControlTransportClass ======== |
| */ |
| public String getControlTransportClass() |
| { |
| return (this.controlTransportClassName); |
| } |
| |
| /* |
| * ======== getDataTransportClass ======== |
| */ |
| public String getDataTransportClass() |
| { |
| return (this.dataTransportClassName); |
| } |
| |
| /* |
| * ======== getEndianess ======== |
| */ |
| public TargetType.Endianess getEndianess() |
| { |
| return (this.endian); |
| } |
| |
| /* |
| * ======== getEventNames ======== |
| */ |
| public String[] getEventNames() |
| { |
| Set<String> keys = evtNameToId.keySet(); |
| |
| return (keys.toArray(new String [0])); |
| } |
| |
| /* |
| * ======== getLogger ======== |
| */ |
| public Logger getLogger(int loggerId) |
| { |
| return (loggers.get(loggerId)); |
| } |
| |
| /* |
| * ======== getLoggerMetaArgs ======== |
| * Returns the meta data associated with the specified logger instance. |
| */ |
| public Node getLoggerMetaArgs(int loggerId) |
| { |
| return (loggers.get(loggerId).metaArgs); |
| } |
| |
| /* |
| * ======== getLoggerNames ======== |
| * Lists all the loggers in the system. |
| */ |
| public String[] getLoggerNames() |
| { |
| return (loggerNames); |
| } |
| |
| /* |
| * ======== getLoggersModules ========= |
| * Returns the list of modules associated with a given logger instance. |
| */ |
| public String[] getLoggersModules(String loggerName) |
| { |
| int loggerId = lookupLoggerId(loggerName); |
| |
| Logger logger = this.loggers.get(loggerId); |
| |
| return (logger.modules.toArray(new String[0])); |
| } |
| |
| /* |
| * ======== getModuleDiagConfig ======== |
| * Gets the initial diagnostics configuration for the given module. |
| */ |
| public DiagConfig getModuleDiagConfig(String moduleName) { |
| return (this.modNameToDiags.get(moduleName)); |
| } |
| |
| /* |
| * ======== getModuleLogger ======== |
| * Returns the logger instance associated with the specified module. |
| */ |
| public String getModuleLogger(String moduleName) { |
| return (this.modNameToLogger.get(moduleName)); |
| } |
| |
| /* |
| * ======== getModuleNames ======== |
| */ |
| public String[] getModuleNames() |
| { |
| Set<String> keys = modNameToId.keySet(); |
| |
| return (keys.toArray(new String [0])); |
| } |
| |
| /* |
| * ======== getOFReader ======== |
| */ |
| public IOFReader getOFReader() |
| { |
| return (ofReader); |
| } |
| |
| /*! |
| * ======== getProperty ======== |
| * Helper function to retrieve the specified target property from the RTA |
| * XML file. |
| * |
| * These target properties are single XML elements whose values are the |
| * text content of the element. |
| */ |
| public String getProperty(Document doc, String name) |
| { |
| /* Retrieve this properties node */ |
| Node n = doc.getElementsByTagName(name).item(0); |
| |
| Node child = n.getFirstChild(); |
| |
| /* Make sure the XML element isn't empty. */ |
| if (child == null) { |
| return (""); |
| } |
| |
| /* Return the value of this property */ |
| return (child.getNodeValue()); |
| } |
| |
| public String getProperty(Element elem, String name) |
| { |
| /* Retrieve the property node. */ |
| Node n = elem.getElementsByTagName(name).item(0); |
| |
| Node child = n.getFirstChild(); |
| |
| /* Make sure the XML element isn't empty. */ |
| if (child == null) { |
| return (""); |
| } |
| |
| /* Return the value of this property */ |
| return (child.getNodeValue()); |
| } |
| |
| /* |
| * ======== getTargetArgSize ======== |
| * Returns the target size of a record argument in bytes (not MAUs). |
| */ |
| public int getTargetArgSize() |
| { |
| return (this.argSize); |
| } |
| |
| /* |
| * ======== getTargetEventRecSize ======== |
| * Returns the record size in bytes (not MAUs). |
| */ |
| public int getTargetEventRecSize() |
| { |
| return (this.eventSize); |
| } |
| |
| /* |
| * ======== getTargetName ======== |
| */ |
| public String getTargetName() |
| { |
| return (this.targetName); |
| } |
| |
| /* |
| * ======== getXMLFromExec ======== |
| * Retrieves the path to a given application's RTA XML file. |
| */ |
| public static String getXMLFromExec(String executable) throws Exception |
| { |
| return (Recap.locateRecap(executable, ".rta.xml")); |
| } |
| |
| /* |
| * ======== lookupEventId ======== |
| */ |
| public int lookupEventId(String eventName) |
| { |
| Integer res = this.evtNameToId.get(eventName); |
| return (res == null ? -1 : res); |
| } |
| |
| /* |
| * ======== lookupEventMessage ======== |
| * Returns the format string for the message with the given name. |
| */ |
| public String lookupEventMessage(String eventName) |
| { |
| return (lookupEventMessage(this.lookupEventId(eventName))); |
| } |
| |
| public String lookupEventMessage(int eventId) { |
| return (this.evtIdToMsg.get(eventId)); |
| } |
| |
| /* |
| * ======== lookupEventModule ======== |
| * The event name contains the module name, e.g., xdc.runtime.Log.L_create |
| */ |
| public String lookupEventModule(String eventName) |
| { |
| return (eventName.substring(0, eventName.lastIndexOf("."))); |
| } |
| |
| /* |
| * ======== lookupEventName ======== |
| */ |
| public String lookupEventName(int eventId) { |
| return (this.evtIdToName.get(eventId)); |
| } |
| |
| /* |
| * ======== lookupLoggerId ======== |
| */ |
| public int lookupLoggerId(String loggerName) |
| { |
| Integer res = this.loggerToId.get(loggerName); |
| return (res == null ? -1 : res); |
| } |
| |
| /* |
| * ======== lookupModuleId ======== |
| */ |
| public int lookupModuleId(String moduleName) |
| { |
| Integer res = this.modNameToId.get(moduleName); |
| return (res == null ? -1 : res); |
| } |
| |
| /* |
| * ======== lookupModuleName ======== |
| */ |
| public String lookupModuleName(int modId) { |
| return (this.modIdToName.get(modId)); |
| } |
| |
| /* |
| * ======== parse ======== |
| * Initialize the MetaData instance with the given paths to the RTA XML |
| * file and executable. |
| */ |
| public String parse(String xmlFile, String executable) |
| { |
| /* Modules */ |
| modNameToId = new HashMap<String, Integer>(); |
| modIdToName = new HashMap<Integer, String>(); |
| modNameToDiags = new HashMap<String, DiagConfig>(); |
| |
| /* Events */ |
| evtNameToId = new HashMap<String, Integer>(); |
| evtIdToName = new HashMap<Integer, String>(); |
| evtIdToMsg = new HashMap<Integer, String>(); |
| |
| /* Loggers */ |
| loggers = new Vector<Logger>(); |
| modNameToLogger = new HashMap<String, String>(); |
| loggerToId = new HashMap<String, Integer>(); |
| |
| Document doc = null; |
| |
| /* Parse the XML file into a Document object. */ |
| try { |
| DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); |
| DocumentBuilder builder = factory.newDocumentBuilder(); |
| doc = builder.parse(new File(xmlFile).toURI().toString()); |
| } |
| catch (javax.xml.parsers.ParserConfigurationException e) { |
| return ("Can't create XML parser: " + e.toString()); |
| } |
| catch (java.io.IOException e) { |
| return ("Can't read RTA XML file " + xmlFile + ": " + e.toString()); |
| } |
| catch (org.xml.sax.SAXException e) { |
| return ("Can't parse RTA XML file " + xmlFile +": " + e.toString()); |
| } |
| |
| /* Retrieve the target-specific properties */ |
| String res = parseTargetProps(doc); |
| if (res != "") { |
| return (res); |
| } |
| |
| /* Retrieve the list of loggers and their properties. */ |
| parseLoggers(doc); |
| |
| /* Retrieve the mapping of modules to ids and the module properties. */ |
| parseModules(doc, xmlFile); |
| |
| /* Retrieve the event information. */ |
| res = parseEventMap(doc, xmlFile); |
| if (res != "") { |
| return (res); |
| } |
| |
| /* Initialize the object file reader. */ |
| res = initOfReader(executable); |
| if (res != "") { |
| return (res); |
| } |
| |
| return (""); |
| } |
| |
| /* |
| * ======== parseFromExec ======== |
| * Retrieves the RTA XML file for the given executable and uses it to |
| * initialize the MetaData object. |
| */ |
| public String parseFromExec(String executable) throws Exception |
| { |
| /* |
| * TODO - Read the parser from the executable using Vers so that |
| * you can use it to extract the embedded recap file. |
| */ |
| |
| /* Retrieve the path to the XML file from the executable. */ |
| String xmlFile = getXMLFromExec(executable); |
| |
| /* Call parse and return the result. */ |
| String result = parse(xmlFile, executable); |
| |
| return (result); |
| } |
| |
| /* |
| * ======== initOfReader ======== |
| * Initialize the object file reader used to retrieve Log_print format |
| * strings. |
| * |
| * The object file reader class name comes from the RTA XML file. |
| */ |
| private String initOfReader(String executable) |
| { |
| /* |
| * If we don't have the executable, or no binary parser class was |
| * specified, don't fail; just don't initialize ofReader. |
| */ |
| if (executable == null) { |
| System.out.println("RTA: Executable not specified, cannot " + |
| "lookup Log_print strings."); |
| return (""); |
| } |
| else if ((this.binaryParserClass == null) || |
| (this.binaryParserClass == "")) { |
| System.out.println("RTA: Binary file parser not specified, " + |
| "cannot lookup Log_print strings."); |
| return (""); |
| } |
| |
| try { |
| /* Instantiate the object file reader. */ |
| Class<?> c = Class.forName(this.binaryParserClass); |
| ofReader = (IOFReader) c.newInstance(); |
| |
| /* Initialize the object file reader. */ |
| String err = ofReader.parse(executable); |
| if (err != "") { |
| return("RTA failed to parse " + executable + ": " + err); |
| } |
| else { |
| /* |
| * Close the file. Reader will re-open it automatically to |
| * read strings. |
| */ |
| ofReader.close(); |
| } |
| } |
| catch (IOException e) { |
| return ("RTA failed to parse object file: " + e); |
| } |
| catch (ClassNotFoundException e) { |
| return ("RTA could not locate the specified binary parser " + |
| "class: " + e); |
| } |
| catch (IllegalAccessException e) { |
| return ("RTA failed to instantiate binary parser class: " + e); |
| } |
| catch (InstantiationException e) { |
| return ("RTA failed to instantiate binary parser class: " + e); |
| } |
| |
| /* |
| * Set the Formatter's OFReader so that it can perform String |
| * lookups (%s) when formatting printf strings. |
| */ |
| Formatter.setOFReader(ofReader); |
| |
| /* Return success. */ |
| return (""); |
| } |
| |
| /* |
| * ======== parseEventMap ======== |
| * Helper function to retrieve all of the event information. |
| */ |
| private String parseEventMap(Document doc, String xmlFile) |
| { |
| /* Get all of the events. */ |
| NodeList evtMap = doc.getElementsByTagName("evtMap"); |
| |
| /* For each event... */ |
| for (int i = 0; i < evtMap.getLength(); i++) { |
| Element elem = (Element) evtMap.item(i); |
| |
| /* Get the event's name in the 'key' attribute */ |
| String name = elem.getAttribute("key"); |
| |
| /* Get the event's id. */ |
| int id = Integer.parseInt(getProperty(elem, "id")); |
| |
| /* Map the event name to id and vice versa. */ |
| this.evtNameToId.put(name, id); |
| this.evtIdToName.put(id, name); |
| |
| /* Get the event's message. */ |
| String msg = getProperty(elem, "msg"); |
| |
| /* Map the event id to the event message. */ |
| try { |
| this.evtIdToMsg.put(id, |
| java.net.URLDecoder.decode(msg, "UTF-8")); |
| } |
| catch (java.io.UnsupportedEncodingException e) { |
| return ("XMl file " + xmlFile + " contains unsupported " + |
| "encodings: " + e.toString()); |
| } |
| } |
| |
| return (""); |
| } |
| |
| /* |
| * ======== parseLoggers ======== |
| * Retrieve the list of loggers so that we have them in the same |
| * order as the target. |
| */ |
| private void parseLoggers(Document doc) |
| { |
| NodeList loggerList = doc.getElementsByTagName("loggers"); |
| for (int i = 0; i < loggerList.getLength(); i++) { |
| Element elem = (Element) loggerList.item(i); |
| Logger logger = new Logger(); |
| |
| /* The log's id is its index in the list. */ |
| logger.id = i; |
| |
| /* Preserve compatibility. Older XML files just have logger name. */ |
| if (elem.getChildNodes().getLength() == 1) { |
| logger.name = elem.getTextContent(); |
| loggers.add(logger); |
| this.loggerToId.put(logger.name, i); |
| |
| continue; |
| } |
| |
| /* Get the logger name. */ |
| logger.name = getProperty(elem, "name"); |
| |
| /* Get the logger type. */ |
| logger.type = getProperty(elem, "type"); |
| |
| /* Get the meta args. */ |
| logger.metaArgs = elem.getElementsByTagName("metaArgs").item(0); |
| |
| /* Map id to logger and logger to id */ |
| loggers.add(logger); |
| this.loggerToId.put(logger.name, i); |
| } |
| |
| /* Create a String array of the logger names for getLoggerNames */ |
| loggerNames = new String[loggers.size()]; |
| for (int i = 0; i < loggers.size(); i++) { |
| loggerNames[i] = loggers.get(i).name; |
| } |
| } |
| |
| /*! |
| * ======== parseModules ======== |
| * Parse the modMap, which maps module names to their id, logger, |
| * and diags settings. |
| */ |
| private void parseModules(Document doc, String xmlFile) |
| { |
| /* Get all of the module nodes. */ |
| NodeList modMap = doc.getElementsByTagName("modMap"); |
| |
| /* For each module... */ |
| for (int i = 0; i < modMap.getLength(); i++) { |
| Element elem = (Element) modMap.item(i); |
| |
| /* Get the module's name which is stored in the 'key' attribute. */ |
| String modName = elem.getAttribute("key"); |
| |
| /* Get the module's id. */ |
| int id = Integer.parseInt(getProperty(elem, "id")); |
| |
| /* Map the module's id to name and vice versa. */ |
| this.modNameToId.put(modName, id); |
| this.modIdToName.put(id, modName); |
| |
| /* Get the module's logger. */ |
| String loggerName = getProperty(elem, "logger"); |
| |
| /* |
| * Map the module to its logger, but don't map modules with a |
| * null logger. |
| */ |
| if (!loggerName.equals("null")) { |
| /* Map module name to logger */ |
| this.modNameToLogger.put(modName, loggerName); |
| |
| /* Map logger to list of modules. */ |
| int loggerId = lookupLoggerId(loggerName); |
| Logger logger = loggers.get(loggerId); |
| logger.modules.add(modName); |
| } |
| |
| /* Get the module's initial diags mask. */ |
| String diagsMask = getProperty(elem, "diagsMask"); |
| |
| /* Create a DiagConfig object from the mask string */ |
| DiagConfig diags = new DiagConfig(diagsMask); |
| |
| /* Map the module to its diags mask. */ |
| this.modNameToDiags.put(modName, diags); |
| } |
| } |
| |
| /*! |
| * ======== parseTargetProps ======== |
| * Helper function to retrieve all of the target properties from the |
| * RTA XML file. |
| */ |
| private String parseTargetProps(Document doc) |
| { |
| /* Name of the target. */ |
| this.targetName = getProperty(doc, "targetName"); |
| |
| /* Get the target endianess. */ |
| String endianStr = getProperty(doc, "endian"); |
| |
| /* Convert the endianess to its enum form. */ |
| try { |
| this.endian = TargetType.strToEndianess(endianStr); |
| } |
| catch (Exception e) { |
| return (e.toString()); |
| } |
| |
| /* Get the target's MAU size. */ |
| this.bitsPerChar = Integer.parseInt(getProperty(doc, "bitsPerChar")); |
| |
| /* Get the MAU size of the IArg type, convert it to bytes. */ |
| this.argSize = Integer.parseInt(getProperty(doc, "argSize")); |
| this.argSize = this.argSize * (this.bitsPerChar / 8); |
| |
| /* Get the MAU size of an event record, convert it to bytes. */ |
| this.eventSize = Integer.parseInt(getProperty(doc, "eventSize")); |
| this.eventSize = this.eventSize * (this.bitsPerChar / 8); |
| |
| /* Get the name of the object file reader class. */ |
| this.binaryParserClass = getProperty(doc, "binaryParser"); |
| |
| /* |
| * Get the class names of the data and control transport classes to |
| * use on the host in communicating with this target application. |
| * |
| * We need to preserve backwards compatibility with XML files that |
| * don't contain this information. Check for it before trying to |
| * retrieve it. |
| */ |
| if (doc.getElementsByTagName("dataTransportClassName").getLength() != 0) { |
| this.dataTransportClassName = |
| getProperty(doc, "dataTransportClassName"); |
| this.controlTransportClassName = |
| getProperty(doc, "controlTransportClassName"); |
| } |
| |
| return (""); |
| } |
| } |