SBlogMapper.cpp
上传用户:xqtpzdz
上传日期:2022-05-21
资源大小:1764k
文件大小:16k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. /****************License************************************************
  2.  * Vocalocity OpenVXI
  3.  * Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  * Vocalocity, the Vocalocity logo, and VocalOS are trademarks or 
  18.  * registered trademarks of Vocalocity, Inc. 
  19.  * OpenVXI is a trademark of Scansoft, Inc. and used under license 
  20.  * by Vocalocity.
  21.  ***********************************************************************/
  22. #define SBLOGMAPPER_EXPORTS
  23. #include "SBlogMapper.h"
  24. #include <map>                  // For STL map template class
  25. #include <string>
  26. #ifdef WIN32
  27. #include <windows.h>
  28. #endif
  29. #if defined(__GNUC__) && (! defined(_GLIBCPP_USE_WCHAR_T))
  30. namespace std
  31. {
  32.   typedef basic_string<wchar_t> wstring;
  33. }
  34. #endif
  35. #ifndef MODULE_PREFIX
  36. #define MODULE_PREFIX  COMPANY_DOMAIN L"."
  37. #endif
  38. #define MODULE_NAME MODULE_PREFIX L"SBlog"
  39. #ifdef HAVE_XERCES
  40. #include <util/PlatformUtils.hpp>       // Xerces headers
  41. #include <parsers/SAXParser.hpp>
  42. #include <sax/HandlerBase.hpp>
  43. using namespace xercesc;
  44. #else
  45. #pragma message("WARNING: HAVE_XERCES not defined, need Apache Xerces to enable the XML error text lookup feature")
  46. #endif
  47. #include "SBlogOSUtils.h"
  48. static const VXIchar *EMPTY_STRING = L"";
  49. // platform independent util functions convert a wide char to int
  50. static int wtoint(const VXIchar *strval)
  51. {
  52.   char mystr[128];
  53.   if( strval == NULL ) return 0;
  54.   SBlogWchar2Latin1(strval, mystr, 127);
  55.   return atoi(mystr);
  56. }
  57. //=================================================================
  58. //
  59. //  ONLY COMPILE IF HAVE_XERCES IS DEFINED
  60. //
  61. //=================================================================
  62. #ifdef HAVE_XERCES
  63. // Error mapper
  64. class SBlogErrorMapper {
  65. public:
  66.   SBlogErrorMapper() : xmlHandler(NULL), initialized(0), 
  67.        parser(NULL), errorLookUpTable(NULL) { }
  68.   virtual ~SBlogErrorMapper();
  69.   
  70.   VXIlogResult ParseErrorMappingFiles(const VXIVector *ErrorMapFiles);
  71.   const VXIchar *GetErrorText(VXIunsigned errorID, const VXIchar *moduleName,
  72.       int *severity);
  73.   
  74.   static void showExceptionMsg(const XMLException& exception);
  75.   static VXIlogResult Error(VXIunsigned errorID, const VXIchar *errorIDText,
  76.     const VXIchar *format, ...);
  77. private:
  78.   VXIlogResult InitializeXMLParser(void);
  79.   
  80.   int moduleNameCmp(const VXIchar *modName, const VXIchar *pattern) const;
  81.     
  82. private:  
  83.   // Internal string type
  84.   typedef std::wstring MyString;
  85.   // Data structure for error table entries
  86.   typedef struct ErrorEntry {
  87.     int severity;
  88.     MyString message;
  89.   } ErrorEntry;
  90.   // Map of error strings
  91.   typedef std::map<VXIunsigned, ErrorEntry> ErrorEntryMap;
  92.   // Data structure for the module mapping table (linked list)
  93.   typedef struct ModuleMappingTable {
  94.     MyString moduleName;
  95.     MyString errFileName;
  96.     ErrorEntryMap errTable;
  97.     struct ModuleMappingTable *next;
  98.   } ModuleMappingTable;
  99.   
  100. private:
  101.   class MySAXHandler;
  102.   MySAXHandler *xmlHandler;
  103.   VXIbool initialized;
  104.   SAXParser *parser;
  105.   ModuleMappingTable *errorLookUpTable;
  106. };
  107. // convert XMLCh char to wide char
  108. static void  XMLCh2VXIchar(const XMLCh * x, VXIchar *output,
  109.    unsigned int maxlen)
  110. {
  111.     if (x == NULL) return;
  112.     unsigned int len = XMLString::stringLen(x);
  113.     if (output == NULL) return;
  114.     for (unsigned int i = 0; i < len + 1 && i < maxlen; ++i)
  115.       // We throw out anything above 0xFFFF
  116.       output[i] = (x[i] != 0 && (x[i] & ~XMLCh(0xFFFF))) ? VXIchar(0xBE)
  117.                                                        : VXIchar(x[i]);
  118. }
  119. class SBlogErrorMapper::MySAXHandler : public HandlerBase {
  120. public:
  121.   MySAXHandler();
  122.   virtual ~MySAXHandler();
  123.   void startElement(const XMLCh* const, AttributeList&);
  124.   void characters(const XMLCh* const chars, const unsigned int length);
  125.   void endElement(const XMLCh* const name);
  126.   void warning(const SAXParseException& exception) 
  127.     { processError(exception, L"Warning"); }
  128.   void error(const SAXParseException& exception) 
  129.     { processError(exception, L"Error"); }
  130.   void fatalError(const SAXParseException& exception) 
  131.     { processError(exception, L"Fatal Error"); }
  132.   void resetData(void)
  133.   {
  134.     errorTable.erase(errorTable.begin(), errorTable.end());
  135.   }
  136.   
  137.   const ErrorEntryMap &getErrorTable(void) const { return errorTable; }
  138.   const MyString &getModuleName(void) const { return moduleName; }
  139. private:
  140.   void processError(const SAXParseException& exception, 
  141.     const VXIchar* errType);
  142.   
  143. private:
  144.   ErrorEntryMap errorTable;
  145.   VXIbool isProcessing;
  146.   VXIunsigned errorNumber;
  147.   int errorSeverity;
  148.   MyString moduleName;
  149.   MyString errorMessage;
  150.   VXIchar tempString[4096];
  151. };
  152. SBlogErrorMapper::MySAXHandler::MySAXHandler() :
  153.   HandlerBase(), errorTable(), moduleName(), errorMessage()
  154. {
  155.   isProcessing = 0;
  156.   errorNumber = 0;
  157.   errorSeverity = -1;
  158. }
  159. SBlogErrorMapper::MySAXHandler::~MySAXHandler()
  160. {
  161. }
  162. void 
  163. SBlogErrorMapper::MySAXHandler::startElement(const XMLCh* const name,
  164.      AttributeList& attributes)
  165. {
  166.   // 1. parse module name from the root
  167.   XMLCh2VXIchar(name, tempString, 4096); 
  168.   if(wcscmp(tempString, L"ErrorMessages") == 0)
  169.   {
  170.     for(unsigned int i = 0; i < attributes.getLength(); i++)
  171.     {
  172.       XMLCh2VXIchar(attributes.getName(i), tempString, 4096); 
  173.       if(wcscmp(tempString, L"moduleName") == 0)
  174.       {
  175.         XMLCh2VXIchar(attributes.getValue(i), tempString, 4096);
  176.         moduleName = tempString;
  177.       }
  178.     }
  179.   }
  180.   // 2. only care about <error> elements
  181.   else if(wcscmp(tempString, L"error") == 0) {
  182.     isProcessing = 1;
  183.     errorMessage = L"";
  184.     // Find the error number and severity (tag attributes)
  185.     for (unsigned int i = 0; i < attributes.getLength(); i++) {
  186.       XMLCh2VXIchar(attributes.getName(i), tempString, 4096); 
  187.       if(wcscmp(tempString, L"num") == 0) {
  188.         XMLCh2VXIchar(attributes.getValue(i), tempString, 4096); 
  189.         errorNumber = wtoint(tempString);
  190.       }
  191.       else if(wcscmp(tempString, L"severity") == 0) {
  192.         XMLCh2VXIchar(attributes.getValue(i), tempString, 4096); 
  193.         errorSeverity = wtoint(tempString);
  194.       }
  195.     }
  196.   }
  197.   else if(wcscmp(tempString, L"advice") == 0) {
  198.     // ignore the advice tag, just concate the advice's message    
  199.   }
  200.   else if(isProcessing)
  201.     errorMessage += L"???"; // Runtime-determined value, unknown
  202. }
  203. void 
  204. SBlogErrorMapper::MySAXHandler::characters(const XMLCh* const chars, 
  205.    const unsigned int length)
  206. {
  207.   // This is the real error message text
  208.   if(isProcessing)
  209.   {
  210.     XMLCh2VXIchar(chars, tempString, 4096); 
  211.     errorMessage += tempString;
  212.   }
  213. }
  214. void SBlogErrorMapper::MySAXHandler::endElement(const XMLCh* const name)
  215. {
  216.   // We only care about <error> elements
  217.   XMLCh2VXIchar(name, tempString, 4096); 
  218.   if(wcscmp(tempString, L"error") == 0) {
  219.     isProcessing = 0;
  220.     // Add error entry to error mapping table (linked list)
  221.     ErrorEntry newEntry;
  222.     newEntry.severity = errorSeverity;
  223.     const VXIchar *sptr = errorMessage.c_str();
  224.     // cutting extra white spaces inside the text
  225.     bool extraSpace = false;
  226.     while( *sptr != L'' )
  227.     {
  228.       if( SBlogIsSpace(*sptr) )
  229.       {
  230.         if( !extraSpace )
  231.         {
  232.           newEntry.message += L' ';
  233.           extraSpace = true;
  234.         }
  235.       }
  236.       else
  237.       {
  238.         newEntry.message += *sptr;
  239.         extraSpace = false;  
  240.       }  
  241.       sptr++;
  242.     } 
  243.     // Add to linked list
  244.     errorTable.insert(ErrorEntryMap::value_type(errorNumber, newEntry));
  245.   }
  246. }
  247. void 
  248. SBlogErrorMapper::MySAXHandler::processError(
  249.    const SAXParseException& exception,
  250.    const VXIchar* errType)
  251. {
  252.   VXIchar ws1[2048];
  253.   VXIchar ws2[2048];
  254.   XMLCh2VXIchar(exception.getMessage() ? exception.getMessage() : (XMLCh*)"NONE", ws1, 2048);
  255.   XMLCh2VXIchar(exception.getSystemId() ? exception.getSystemId() : (XMLCh*)"NONE", ws2, 2048);
  256.   
  257.   Error(352, L"SBlogListeners: XML error lookup file parse failed",
  258. L"%s%s%s%s%s%s%s%u%s%u", L"errType", errType, L"errMsg", ws1,
  259. L"file", ws2,
  260. L"line", exception.getLineNumber(), 
  261. L"column", exception.getColumnNumber());
  262. }
  263. void 
  264. SBlogErrorMapper::showExceptionMsg(const XMLException& exception)
  265. {
  266.   VXIchar ws1[4096];
  267.   XMLCh2VXIchar(exception.getMessage(), ws1, 4096);
  268.   Error(353, L"SBlogListeners: XML parser exception", L"%s%s",
  269. L"exception", ws1);
  270. }
  271. VXIlogResult 
  272. SBlogErrorMapper::Error(VXIunsigned errorID, const VXIchar *errorIDText,
  273. const VXIchar *format, ...)
  274. {
  275.   va_list args;
  276.   va_start(args, format);
  277.   VXIlogResult rc = SBlogVLogErrorToConsole(MODULE_NAME, errorID, errorIDText,
  278.     format, args);
  279.   va_end(args);
  280.   return rc;
  281. }
  282. VXIlogResult SBlogErrorMapper::InitializeXMLParser()
  283. {
  284.   if( initialized ) return VXIlog_RESULT_SUCCESS;
  285.   // Initialize the SAX parser
  286.   try {
  287.     XMLPlatformUtils::Initialize();
  288.   }
  289.   catch (const XMLException& exception) {
  290.     showExceptionMsg(exception);
  291.     return VXIlog_RESULT_FAILURE;
  292.   }
  293.   initialized = 1;
  294.   parser = new SAXParser();
  295.   parser->setDoValidation(false);
  296.   parser->setDoNamespaces(false);
  297.   // Register our own handler class (callback)
  298.   xmlHandler = new MySAXHandler();
  299.   ErrorHandler* errHandler = (ErrorHandler*) xmlHandler;
  300.   parser->setDocumentHandler((DocumentHandler *)xmlHandler);
  301.   parser->setErrorHandler(errHandler);  
  302.   
  303.   return VXIlog_RESULT_SUCCESS;
  304. }
  305. VXIlogResult
  306. SBlogErrorMapper::ParseErrorMappingFiles(const VXIVector *errorMapFiles)
  307. {
  308.   VXIlogResult rc = VXIlog_RESULT_SUCCESS;
  309.   if ( errorMapFiles == NULL ) return rc;
  310.   InitializeXMLParser();
  311.   
  312.   char narrowFileToParse[4096];
  313.   VXIunsigned len = VXIVectorLength(errorMapFiles);
  314.   const VXIValue *xmlFilePtr = NULL;
  315.   const VXIchar  *xmlFile = NULL;
  316.   for(VXIunsigned i = 0; i < len; ++i)
  317.   {
  318.     xmlFilePtr = VXIVectorGetElement(errorMapFiles, i); 
  319.     if( VXIValueGetType(xmlFilePtr) == VALUE_STRING )
  320.     {
  321.       xmlFile = VXIStringCStr((const VXIString *)xmlFilePtr);
  322.       SBlogWchar2Latin1(xmlFile, narrowFileToParse, 4095);
  323.       // Let the SAX parser do its job, it will call our handler callbacks
  324.       try 
  325.       {
  326.         xmlHandler->resetData();
  327.         parser->parse(narrowFileToParse);
  328.       }
  329.       catch (const XMLException& exception) 
  330.       {
  331.         showExceptionMsg(exception);
  332.         // skip and processing next file
  333.         continue;
  334.       }  
  335.       if( xmlHandler->getErrorTable().size() > 0 )
  336.       {
  337.         ModuleMappingTable *map = new ModuleMappingTable;
  338.         if( map )
  339.         {
  340.           map->next = NULL;
  341.           map->moduleName = xmlHandler->getModuleName();
  342.           map->errFileName = xmlFile; 
  343.           map->errTable = xmlHandler->getErrorTable();
  344.           if( errorLookUpTable == NULL )
  345.           {
  346.             errorLookUpTable = map;
  347.           }
  348.           else
  349.           {
  350.             map->next = errorLookUpTable;
  351.             errorLookUpTable = map;
  352.           }
  353.         }
  354.         else
  355.         {
  356.           return VXIlog_RESULT_FAILURE;  
  357.         }
  358.       } // end-if getErrorTable()
  359.     } 
  360.   }  
  361.   return VXIlog_RESULT_SUCCESS;  
  362. }
  363. int 
  364. SBlogErrorMapper::moduleNameCmp(const VXIchar *modName, 
  365. const VXIchar *pattern) const
  366. {
  367.   if( modName == NULL || pattern == NULL ) return 1;
  368.   if( modName == NULL && pattern == NULL ) return 0;
  369.   // if it is wildcard, search for identical pattern
  370.   if( *pattern == L'*' )
  371.   {
  372.     unsigned int len1 = wcslen(modName), len2 = wcslen(pattern);
  373.     if( len1 < len2-1) return 1;
  374.     while( len2 > 0 )
  375.     {
  376.       if( modName[len1] != pattern[len2] ) return 1;
  377.       len2--;
  378.       len1--;
  379.     }
  380.   }
  381.   else
  382.   {
  383.     // do an exact match comparison
  384.     return wcscmp(modName, pattern);
  385.   }
  386.   return 0;
  387. }
  388. const VXIchar *
  389. SBlogErrorMapper::GetErrorText(VXIunsigned errorID,
  390.        const VXIchar *moduleName,
  391.        int *severity)
  392. {
  393.   if( errorLookUpTable )
  394.   {
  395.     ModuleMappingTable *p = errorLookUpTable;
  396.     while( p )
  397.     { 
  398.       // search for matched module name, wildcard is supported
  399.       if( moduleNameCmp(moduleName, p->moduleName.c_str()) == 0 )
  400.       {
  401.         // found matched module name, find the error number
  402. ErrorEntryMap::const_iterator vi = p->errTable.find(errorID);
  403. if ( vi != p->errTable.end() )
  404.         {
  405.   if( severity ) *severity = (*vi).second.severity;
  406.   return (*vi).second.message.c_str();
  407. }
  408. else
  409. {
  410.   return EMPTY_STRING;
  411. }
  412.       }
  413.       p = p->next;
  414.     }
  415.   }  
  416.   return EMPTY_STRING;
  417. }
  418. // destructor
  419. SBlogErrorMapper::~SBlogErrorMapper()
  420. {
  421.   if( xmlHandler ) delete xmlHandler;
  422.   if( parser ) delete parser;
  423.   if( errorLookUpTable )
  424.   {
  425.     ModuleMappingTable *p = errorLookUpTable, *d = NULL;
  426.     while( p )
  427.     {
  428.       d = p;
  429.       p = p->next;
  430.       delete d;
  431.     }
  432.     errorLookUpTable = NULL;
  433.   }
  434. }
  435. //=================================================================
  436. //
  437. //  ONLY COMPILE IF HAVE_XERCES IS DEFINED
  438. //
  439. //=================================================================
  440. #endif  // HAVE_XERCES
  441. /**
  442.  * Create a new XML error mapper
  443.  *
  444.  * @param errorMapFiles   [IN] VXIVector of local OpenSpeech Browser PIK
  445.  *                             XML error mapping files
  446.  * @param mapper          [OUT] Handle to the error mapper
  447.  *
  448.  * @result VXIlog_RESULT_SUCCESS on success 
  449.  */
  450. SBLOGMAPPER_API VXIlogResult 
  451. SBlogErrorMapperCreate(const VXIVector    *errorMapFiles,
  452.        SBlogErrorMapper  **mapper)
  453. {
  454.   if (! mapper)
  455.     return VXIlog_RESULT_INVALID_ARGUMENT;
  456. #ifdef HAVE_XERCES
  457.   *mapper = new SBlogErrorMapper;
  458.   if (! *mapper)
  459.     return VXIlog_RESULT_OUT_OF_MEMORY;
  460.   VXIlogResult rc = (*mapper)->ParseErrorMappingFiles(errorMapFiles);
  461.   if (rc != VXIlog_RESULT_SUCCESS) {
  462.     delete *mapper;
  463.     *mapper = NULL;
  464.   }
  465.   return VXIlog_RESULT_SUCCESS;
  466. #else
  467.   return VXIlog_RESULT_UNSUPPORTED;
  468. #endif
  469. }
  470. /**
  471.  * Destroy an XML error mapper
  472.  *
  473.  * @param mapper          [IN/OUT] Handle to the error mapper, set
  474.  *                                 to NULL on success
  475.  *
  476.  * @result VXIlog_RESULT_SUCCESS on success 
  477.  */
  478. SBLOGMAPPER_API VXIlogResult
  479. SBlogErrorMapperDestroy(SBlogErrorMapper **mapper)
  480. {
  481.   if ((! mapper) || (! *mapper))
  482.     return VXIlog_RESULT_INVALID_ARGUMENT;
  483. #ifdef HAVE_XERCES
  484.   delete *mapper;
  485.   *mapper = NULL;
  486.   return VXIlog_RESULT_SUCCESS;
  487. #else
  488.   return VXIlog_RESULT_UNSUPPORTED;
  489. #endif
  490. }
  491. /**
  492.  * Map an error ID to text and a severity
  493.  *
  494.  * @param mapper      [IN] Handle to the error mapper
  495.  * @param errorID     [IN] Error ID to map as passed to VXIlog::Error( )
  496.  * @param moduleName  [IN] Module name reporting the error as passed to
  497.  *                         VXIlog::Error( )
  498.  * @param errorText   [OUT] Error text as defined in the error mapping
  499.  *                          file. Owned by the error text mapper, must
  500.  *                          not be modified or freed.
  501.  * @param severity    [OUT] Severity identifier as defined in the error
  502.  *                          mapping file. Owned by the error text mapper,
  503.  *                          must not be modified or freed. Typically one
  504.  *                          of the following:
  505.  *                            0 -> UNKNOWN (no mapping found)
  506.  *                            1 -> CRITICAL
  507.  *                            2 -> SEVERE
  508.  *                            3 -> WARNING
  509.  *
  510.  * @result VXIlog_RESULT_SUCCESS on success 
  511.  */
  512. SBLOGMAPPER_API VXIlogResult
  513. SBlogErrorMapperGetErrorInfo(SBlogErrorMapper  *mapper,
  514.      VXIunsigned        errorID,
  515.      const VXIchar     *moduleName,
  516.      const VXIchar    **errorText,
  517.      VXIint            *severityLevel)
  518. {
  519. #ifdef HAVE_XERCES
  520.   *errorText = mapper->GetErrorText(errorID, moduleName, severityLevel);
  521. #else
  522.   *errorText = EMPTY_STRING;
  523. #endif
  524.   return (*errorText ? VXIlog_RESULT_SUCCESS : VXIlog_RESULT_NON_FATAL_ERROR);
  525. }