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

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. #include "DocumentParser.hpp"
  23. #include "DocumentStorage.hpp"
  24. #include "CommonExceptions.hpp"
  25. #include "SimpleLogger.hpp"
  26. #include "VXML.h"                    // for attribute names
  27. #include "DocumentConverter.hpp"     // for DocumentConverter
  28. #include "PropertyList.hpp"
  29. #include "XMLChConverter.hpp"
  30. #include "ValueLogging.hpp"     // for VXIValue dumping
  31. #include "VXIinet.h"
  32. // Internal documents
  33. #include "Schema.hpp"
  34. // Xerces related
  35. #ifndef HAVE_XERCES
  36. #error Need Apache Xerces to build the VoiceXML interpreter
  37. #endif
  38. #include <util/PlatformUtils.hpp>
  39. #include <util/TransService.hpp>
  40. #include <sax2/XMLReaderFactory.hpp>
  41. #include <framework/MemBufInputSource.hpp>
  42. #include <sax/SAXParseException.hpp> // by ErrorReporter
  43. #include <sax/EntityResolver.hpp>    // by DTDResolver
  44. #include <sax/ErrorHandler.hpp>      // by ErrorReporter
  45. #include <validators/common/Grammar.hpp>
  46. #include <xercesc/dom/DOMImplementation.hpp>
  47. #include <xercesc/dom/DOMImplementationLS.hpp>
  48. #include <xercesc/dom/DOMImplementationRegistry.hpp>
  49. #include <xercesc/dom/DOMBuilder.hpp>
  50. #include <xercesc/dom/DOMException.hpp>
  51. #include <xercesc/dom/DOMDocument.hpp>
  52. #include <xercesc/dom/DOMErrorHandler.hpp>
  53. #include <xercesc/dom/DOMLocator.hpp>
  54. #include <xercesc/framework/Wrapper4InputSource.hpp>
  55. using namespace xercesc;
  56. //#############################################################################
  57. // Utilities - these are specific to Xerces
  58. //#############################################################################
  59. class ErrorReporter : public ErrorHandler {
  60. public:
  61.   ErrorReporter()  { }
  62.   ~ErrorReporter() { }
  63.   
  64.   void warning(const SAXParseException& toCatch)     { /* Ignore */ }
  65.   void fatalError(const SAXParseException& toCatch)  { error(toCatch); }
  66.   void resetErrors() { }
  67.   void error(const SAXParseException & toCatch)
  68.   { throw SAXParseException(toCatch); }
  69. private:
  70.   ErrorReporter(const ErrorReporter &);
  71.   void operator=(const ErrorReporter &);
  72. };
  73. class VXIDOMException
  74. {
  75. public:
  76.   VXIDOMException(const DOMError& domError) {
  77.     XMLChToVXIchar uri(domError.getLocation()->getURI());
  78.     XMLChToVXIchar message(domError.getMessage());
  79.     _uri = uri.c_str();
  80.     _message = message.c_str();
  81.     _line = domError.getLocation()->getLineNumber();
  82.     _col = domError.getLocation()->getColumnNumber();
  83.   }
  84.   vxistring getURI() const { return _uri; }
  85.   vxistring getMessage() const { return _message; }
  86.   int getLine() const { return _line; }
  87.   int getColumn() const { return _col; }
  88. private:
  89.   vxistring _uri;
  90.   vxistring _message;
  91.   int       _line;
  92.   int       _col;
  93. };
  94. class DOMErrorReporter : public DOMErrorHandler
  95. {
  96. public:
  97. DOMErrorReporter(){}
  98. ~DOMErrorReporter(){}
  99. bool handleError(const DOMError& domError) {
  100. throw VXIDOMException(domError);
  101. return true;
  102. }
  103. private :
  104.     DOMErrorReporter(const DOMErrorReporter&);
  105.     void operator=(const DOMErrorReporter&);
  106. };
  107. class DTDResolver : public EntityResolver {
  108. public:
  109.   virtual ~DTDResolver() { }
  110.   DTDResolver() { }
  111.   virtual InputSource * resolveEntity(const XMLCh * const publicId,
  112.                                       const XMLCh * const systemId)
  113.   {
  114.     if (publicId && Compare(publicId, L"SB_Defaults")) {
  115.       VXIcharToXMLCh name(L"VXML Defaults DTD (for SB 1.0)");
  116.       return new MemBufInputSource(VALIDATOR_DATA + VALIDATOR_DEFAULTS_DTD,
  117.                                    VALIDATOR_DEFAULTS_DTD_SIZE,
  118.                                    name.c_str(), false);
  119.     }
  120.     
  121.     if( systemId ) {
  122.       if (Compare(systemId, L"http://www.w3.org/TR/voicexml20/vxml.xsd")) {
  123.         VXIcharToXMLCh name(L"http://www.w3.org/TR/voicexml21/vxml.xsd (SB)");
  124.         return new MemBufInputSource(VALIDATOR_DATA + VALIDATOR_VXML,
  125.                                      VALIDATOR_VXML_SIZE,
  126.                                      name.c_str(), false);
  127.       }
  128.       if (Compare(systemId, L"http://www.w3.org/TR/voicexml21/vxml.xsd")) {
  129.         VXIcharToXMLCh name(L"http://www.w3.org/TR/voicexml21/vxml.xsd (SB)");
  130.         return new MemBufInputSource(VALIDATOR_DATA + VALIDATOR_VXML,
  131.                                      VALIDATOR_VXML_SIZE,
  132.                                      name.c_str(), false);
  133.       }
  134.   if (Compare(systemId, L"vxml-datatypes.xsd")) {
  135.         VXIcharToXMLCh name(L"vxml-datatypes.xsd (SB)");
  136.         return new MemBufInputSource(VALIDATOR_DATA + VALIDATOR_VXML_DATA,
  137.                                      VALIDATOR_VXML_DATA_SIZE,
  138.                                      name.c_str(), false);
  139.       }
  140.   
  141.       if (Compare(systemId, L"vxml-attribs.xsd")) {
  142.         VXIcharToXMLCh name(L"vxml-attribs.xsd (SB)");
  143.         return new MemBufInputSource(VALIDATOR_DATA + VALIDATOR_VXML_ATTR,
  144.                                      VALIDATOR_VXML_ATTR_SIZE,
  145.                                      name.c_str(), false);
  146.       }
  147.   
  148.       if (Compare(systemId, L"vxml-grammar-extension.xsd")) {
  149.         VXIcharToXMLCh name(L"vxml-grammar-extension.xsd (SB)");
  150.         return new MemBufInputSource(VALIDATOR_DATA + VALIDATOR_SRGF_EXTN,
  151.                                      VALIDATOR_SRGF_EXTN_SIZE,
  152.                                      name.c_str(), false);
  153.       }
  154.   
  155.       if (Compare(systemId, L"vxml-grammar-restriction.xsd")) {
  156.         VXIcharToXMLCh name(L"vxml-grammar-restriction.xsd (SB)");
  157.         return new MemBufInputSource(VALIDATOR_DATA + VALIDATOR_SRGF_RSTR,
  158.                                      VALIDATOR_SRGF_RSTR_SIZE,
  159.                                      name.c_str(), false);
  160.       }
  161.   
  162.       if (Compare(systemId, L"vxml-synthesis-extension.xsd")) {
  163.         VXIcharToXMLCh name(L"vxml-synthesis-extension.xsd (SB)");
  164.         return new MemBufInputSource(VALIDATOR_DATA + VALIDATOR_SSML_EXTN,
  165.                                      VALIDATOR_SSML_EXTN_SIZE,
  166.                                      name.c_str(), false);
  167.       }
  168.   
  169.       if (Compare(systemId, L"vxml-synthesis-restriction.xsd")) {
  170.         VXIcharToXMLCh name(L"vxml-synthesis-restriction.xsd (SB)");
  171.         return new MemBufInputSource(VALIDATOR_DATA + VALIDATOR_SSML_RSTR,
  172.                                      VALIDATOR_SSML_RSTR_SIZE,
  173.                                      name.c_str(), false);
  174.       }
  175.   
  176.       if (Compare(systemId, L"synthesis-core.xsd")) {
  177.         VXIcharToXMLCh name(L"synthesis-core.xsd (SB)");
  178.         return new MemBufInputSource(VALIDATOR_DATA + VALIDATOR_SSML_CORE,
  179.                                      VALIDATOR_SSML_CORE_SIZE,
  180.                                      name.c_str(), false);
  181.       }
  182.   
  183.       if (Compare(systemId, L"grammar-core.xsd")) {
  184.         VXIcharToXMLCh name(L"grammar-core.xsd (SB)");
  185.         return new MemBufInputSource(VALIDATOR_DATA + VALIDATOR_SRGF_CORE,
  186.                                      VALIDATOR_SRGF_CORE_SIZE,
  187.                                      name.c_str(), false);
  188.       }
  189.   
  190.       if (Compare(systemId, L"http://www.w3.org/2001/xml.xsd")) {
  191.         VXIcharToXMLCh name(L"http://www.w3.org/2001/xml.xsd (SB)");
  192.         return new MemBufInputSource(VALIDATOR_DATA + VALIDATOR_XML,
  193.                                      VALIDATOR_XML_SIZE,
  194.                                      name.c_str(), false);
  195.       }
  196.   
  197.       if (Compare(systemId, L"XMLSchema.dtd")) {
  198.         VXIcharToXMLCh name(L"XMLSchema.dtd (SB)");
  199.         return new MemBufInputSource(VALIDATOR_DATA + VALIDATOR_SCHEMA_DTD,
  200.                                      VALIDATOR_SCHEMA_DTD_SIZE,
  201.                                      name.c_str(), false);
  202.       }
  203.       
  204.       if (Compare(systemId, L"datatypes.dtd")) {
  205.         VXIcharToXMLCh name(L"datatypes.dtd (SB)");
  206.         return new MemBufInputSource(VALIDATOR_DATA + VALIDATOR_DATATYPE_DTD,
  207.                                      VALIDATOR_DATATYPE_DTD_SIZE,
  208.                                      name.c_str(), false);
  209.       }
  210.   
  211.       if ( ( publicId && 
  212.   Compare(publicId, L"-//W3C//DTD VOICEXML 2.0//EN")  ||
  213.   Compare(publicId, L"-//W3C//DTD VOICEXML 2.1//EN")) ||
  214.           Compare(systemId, L"http://www.w3.org/TR/voicexml20/vxml.dtd") || 
  215.   Compare(systemId, L"http://www.w3.org/TR/voicexml21/vxml.dtd"))
  216.       {
  217.         VXIcharToXMLCh name(L"VXML DTD (SB)");
  218.         return new MemBufInputSource(VALIDATOR_DATA + VALIDATOR_VXML_DTD,
  219.                                      VALIDATOR_VXML_DTD_SIZE,
  220.                                      name.c_str(), false);
  221.       }
  222.     }
  223.     // If the id is not supported by VXI, return NULL so that
  224.     // xerces will fetch the id itself
  225.     return NULL;
  226.   }
  227. };
  228. //#############################################################################
  229. // Document Parser
  230. //#############################################################################
  231. // xerces crashes when on multi-thread app. that simultaneously load schema
  232. // grammar therefore use a global mutext to restrict access to only thread
  233. // at a time
  234. static VXItrdMutex* gblXMLGrammarMutex = NULL;
  235. bool DocumentParser::Initialize(unsigned int cacheSize)
  236. {
  237.   try {
  238.     VXItrdMutexCreate(&gblXMLGrammarMutex);
  239.     XMLPlatformUtils::Initialize();
  240.     if (!VXMLDocumentModel::Initialize()) return false;
  241.     DocumentConverter::Initialize();
  242.   }
  243.   catch (const XMLException &) {
  244.     return false;
  245.   }
  246.   DocumentStorageSingleton::Initialize(cacheSize);
  247.   return true;
  248. }
  249. void DocumentParser::Deinitialize()
  250. {
  251.   DocumentStorageSingleton::Deinitialize();
  252.   try {
  253.     VXItrdMutexDestroy(&gblXMLGrammarMutex);
  254.     DocumentConverter::Deinitialize();
  255.     VXMLDocumentModel::Deinitialize();
  256.     XMLPlatformUtils::Terminate();
  257.   }
  258.   catch (const XMLException &) {
  259.     // do nothing
  260.   }
  261. }
  262. static void LockLoadGrammar(void)
  263. {
  264.   if( gblXMLGrammarMutex ) VXItrdMutexLock(gblXMLGrammarMutex);
  265. }
  266. static void UnlockLoadGrammar(void)
  267. {
  268.   if( gblXMLGrammarMutex ) VXItrdMutexUnlock(gblXMLGrammarMutex);
  269. }  
  270. DocumentParser::DocumentParser()
  271.   : parser(NULL), converter(NULL), loadedVXML20(false)
  272. {
  273.   converter = new DocumentConverter();
  274.   if (converter == NULL) throw VXIException::OutOfMemory();
  275.   parser = XMLReaderFactory::createXMLReader();
  276.   if (parser == NULL) {
  277.     delete converter;
  278.     throw VXIException::OutOfMemory();
  279.   }
  280.   DTDResolver * dtd = new DTDResolver();
  281.   if (dtd == NULL) {
  282.     delete converter;
  283.     delete parser;
  284.     throw VXIException::OutOfMemory();
  285.   }
  286.   parser->setEntityResolver(dtd);
  287.   // These settings below should not change the Xerces defaults.  Their
  288.   // presence makes the defaults explicit.
  289.   parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
  290.   parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
  291.   parser->setFeature(XMLUni::fgXercesDynamic, false);
  292.   parser->setFeature(XMLUni::fgXercesSchema, true);
  293.   parser->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
  294.   parser->setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, false);
  295.   ErrorHandler *errReporter = new ErrorReporter();
  296.   parser->setErrorHandler(errReporter);
  297.   parser->setContentHandler(converter);
  298.   parser->setLexicalHandler(converter);
  299.   // this is rather wasteful... but the only way to get
  300.   // the document encoding.  this is only done so that
  301.   // integrators could convert grammars or ssml docs
  302.   // back to the original encoding if needed.
  303.   parser->installAdvDocHandler(this);
  304. }
  305. DocumentParser::~DocumentParser()
  306. {
  307.   if (parser != NULL) {
  308.     const ErrorHandler * reporter = parser->getErrorHandler();
  309.     delete reporter;
  310.     const EntityResolver * resolver = parser->getEntityResolver();
  311.     delete resolver;
  312.     delete parser;
  313.     delete converter;
  314.     parser = NULL;
  315.   }
  316.   while(!domParsers.empty()){
  317.     xercesc::DOMBuilder *domParser = domParsers.front();
  318. domParsers.pop_front();
  319. DOMErrorReporter *domReporter = (DOMErrorReporter *) domParser->getErrorHandler();
  320.     if(domReporter) delete domReporter;
  321.     domParser->release();
  322.   }
  323. }
  324. //****************************************************************************
  325. // FetchBuffer
  326. //****************************************************************************
  327. // 1: Invalid parameter
  328. // 2: Unable to open URL
  329. // 3: Unable to read from URL
  330. int DocumentParser::FetchBuffer(const VXIchar * url,
  331.                                 const VXIMapHolder & properties,
  332.                                 VXIMapHolder & streamInfo,
  333.                                 VXIinetInterface * inet,
  334.                                 SimpleLogger & log,
  335.                                 const VXIbyte * & result,
  336.                                 VXIulong & read,
  337.                                 vxistring & docURL)
  338. {
  339.   if (log.IsLogging(2)) {
  340.     log.StartDiagnostic(2) << L"DocumentParser::FetchBuffer(" << url
  341.                            << L", " << properties.GetValue() << L")";
  342.     log.EndDiagnostic();
  343.   }
  344.   // Set url for error report
  345.   log.SetUri( url ? url : L"NONE" );
  346.   
  347.   if (inet == NULL || url == NULL || wcslen(url) == 0) return 1;
  348.     
  349.   // (1) Open URL
  350.   VXIinetStream * stream;
  351.   // VXIMapHolder streamInfo;
  352.   if (streamInfo.GetValue() == NULL) 
  353.   {
  354.     return -1;
  355.   }
  356.   
  357.   if (inet->Open(inet, L"vxi", url, INET_MODE_READ, 0, properties.GetValue(),
  358.                  streamInfo.GetValue(), &stream) != 0)
  359.   {
  360.     if (log.IsLogging(0)) {
  361.       log.StartDiagnostic(0) << L"DocumentParser::FetchBuffer - could not "
  362.         L"open URL: " << url;
  363.       log.EndDiagnostic();
  364.     }
  365.     return 2;
  366.   }
  367.   
  368.   // (2) Determine document size & read into local memory buffer.
  369.   const VXIValue * tempURL = NULL;
  370.   tempURL = VXIMapGetProperty(streamInfo.GetValue(), INET_INFO_ABSOLUTE_NAME);
  371.   if (tempURL == NULL || VXIValueGetType(tempURL) != VALUE_STRING) {
  372.     inet->Close(inet, &stream);
  373.     if (log.IsLogging(0)) {
  374.       log.StartDiagnostic(0) << L"DocumentParser::FetchBuffer - could not "
  375.         L"retrieve absolute path of document at URL: " << url;
  376.       log.EndDiagnostic();
  377.     }
  378.     return 2;
  379.   }
  380.   docURL = VXIStringCStr(reinterpret_cast<const VXIString *>(tempURL));
  381.   const VXIValue * tempSize = NULL;
  382.   tempSize = VXIMapGetProperty(streamInfo.GetValue(), INET_INFO_SIZE_BYTES);
  383.   if (tempSize == NULL || VXIValueGetType(tempSize) != VALUE_INTEGER) {
  384.     inet->Close(inet, &stream);
  385.     if (log.IsLogging(0)) {
  386.       log.StartDiagnostic(0) << L"DocumentParser::FetchBuffer - could not "
  387.         L"retrieve size of document at URL: " << url;
  388.       log.EndDiagnostic();
  389.     }
  390.     return 2;
  391.   }
  392.   VXIint32 bufSize
  393.     = VXIIntegerValue(reinterpret_cast<const VXIInteger *>(tempSize));
  394.   if (bufSize < 2047)
  395.     bufSize = 2047;
  396.   ++bufSize;
  397.   VXIbyte * buffer = new VXIbyte[bufSize];
  398.   if(buffer == NULL) {
  399.     log.LogError(202);
  400.     return -1;
  401.   }
  402.   bool reachedEnd = false; 
  403.   read = 0;
  404.   while (!reachedEnd) {
  405.     VXIulong bytesRead = 0;
  406.     switch (inet->Read(inet, buffer+read, bufSize-read, &bytesRead, stream)) {
  407.     case VXIinet_RESULT_SUCCESS:
  408.       read += bytesRead;
  409.       break;
  410.     case VXIinet_RESULT_END_OF_STREAM:
  411.       read += bytesRead;
  412.       reachedEnd = true;  // exit while
  413.       break;
  414.     case VXIinet_RESULT_WOULD_BLOCK:
  415.       VXItrdThreadYield();
  416.       break;
  417.     default:
  418.       inet->Close(inet, &stream);
  419.       delete[] buffer;
  420.       log.LogDiagnostic(0, L"DocumentParser::FetchBuffer - "
  421.                         L"could not read from URL.");
  422.       return 3;
  423.     }
  424.     if (read == static_cast<VXIulong>(bufSize)) {
  425.       // The number of bytes read exceeds the number expected.  Double the
  426.       // size and keep reading.
  427.       VXIbyte * temp = new VXIbyte[2*bufSize];
  428.       if(temp == NULL) {
  429.         log.LogError(202);
  430.         delete [] buffer;
  431.         return -1;
  432.       }
  433.       memcpy(static_cast<void *>(temp), static_cast<void *>(buffer),
  434.              bufSize * sizeof(VXIbyte));
  435.       delete[] buffer;
  436.       buffer = temp;
  437.       bufSize *= 2;
  438.     }
  439.   }
  440.   inet->Close(inet, &stream);
  441.   result = buffer;
  442.   log.LogDiagnostic(2, L"DocumentParser::FetchBuffer - success");
  443.   return 0;
  444. }
  445. void DocumentParser::ReleaseBuffer(const VXIbyte * & buffer)
  446. {
  447.   if (buffer != VALIDATOR_DATA + VXML_DEFAULTS)
  448.     delete[] const_cast<VXIbyte *>(buffer);
  449.   buffer = NULL;
  450. }
  451. //#############################################################################
  452. // FetchDocument
  453. //#############################################################################
  454. // -2: Internal error
  455. int DocumentParser::FetchDocument(const VXIchar * url,
  456.                                   const VXIMapHolder & properties,
  457.                                   VXIinetInterface * inet,
  458.                                   VXIcacheInterface * cache,
  459.                                   SimpleLogger & log,
  460.                                   VXMLDocument & document,
  461.                                   VXIMapHolder & docProperties,
  462.                                   bool isDefaults,
  463.                                   bool isRootApp,
  464.                                   VXIbyte **content,
  465.                                   VXIulong *size)
  466. {
  467.   int result;
  468.   if (log.IsLogging(2)) {
  469.     log.StartDiagnostic(2) << L"DocumentParser::FetchDocument(" << url << L")";
  470.     log.EndDiagnostic();
  471.   }
  472.   // (1) Load the VXML DTD for validation.  This will override an externally
  473.   // specified DTD if the user provides a link.
  474.   try {
  475.     if (isDefaults) {
  476.       MemBufInputSource membuf(
  477.           VALIDATOR_DATA + DUMMY_VXML_DEFAULTS_DOC,
  478.           DUMMY_VXML_DEFAULTS_DOC_SIZE,
  479.           "vxml 1.0 defaults");
  480.       parser->parse(membuf);
  481.       converter->ResetDocument(); // Throw this document away.
  482.     }
  483.     if (!isDefaults && !loadedVXML20) {
  484.       // Preload the VXML 2.1 schema.
  485.       VXIcharToXMLCh name(L"http://www.w3.org/TR/voicexml21/vxml.xsd");
  486.       LockLoadGrammar();
  487.       parser->loadGrammar(name.c_str(), Grammar::SchemaGrammarType, true);
  488.       // Reuse cached grammars if available.
  489.       parser->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);      
  490.       UnlockLoadGrammar(); 
  491.       loadedVXML20 = true;
  492.     }
  493.   }
  494.   catch (const XMLException & exception) {
  495.     if (!isDefaults && !loadedVXML20) 
  496.       UnlockLoadGrammar();  
  497.       
  498.     XMLChToVXIchar message(exception.getMessage());
  499.     log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - XML parsing "
  500.       L"error from DOM: " << message;
  501.     log.EndDiagnostic();
  502.     log.LogError(999, SimpleLogger::MESSAGE, L"unable to load VXML DTD");
  503.     return 4;
  504.   }
  505.   catch (const SAXParseException & exception) {
  506.     if (!isDefaults && !loadedVXML20) 
  507.       UnlockLoadGrammar();  
  508.       
  509.     XMLChToVXIchar sysid(exception.getSystemId());
  510.     XMLChToVXIchar message(exception.getMessage());
  511.     log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - Parse error "
  512.                            << L"in file "" 
  513.                            << sysid 
  514.                            << L"", line " << exception.getLineNumber()
  515.                            << L", column " << exception.getColumnNumber()
  516.                            << L" - " << message;
  517.     log.EndDiagnostic();
  518.     log.LogError(999, SimpleLogger::MESSAGE, L"unable to load VXML DTD");
  519.     return 4;
  520.   }
  521.   catch (...) {
  522.     if (!isDefaults && !loadedVXML20) 
  523.       UnlockLoadGrammar();  
  524.     log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - Unknown Parse error";
  525.     log.EndDiagnostic();
  526.     log.LogError(999, SimpleLogger::MESSAGE, L"unable to load VXML DTD");
  527.     return 4;          
  528.   }
  529.   // (2) Load the url into memory.
  530.   const VXIbyte * buffer = NULL;
  531.   VXIulong bufSize = 0;
  532.   vxistring docURL;
  533.   bool isDefaultDoc = false;
  534.   
  535.   if (isDefaults && wcslen(url) == 0) {
  536.     buffer  = VALIDATOR_DATA + VXML_DEFAULTS;
  537.     bufSize = VXML_DEFAULTS_SIZE;
  538.     docURL = L"builtin defaults";
  539.     result = 0;
  540.     isDefaultDoc = true;
  541.   }
  542.   else {
  543.     result = DocumentParser::FetchBuffer(url, properties, docProperties, inet, log,
  544.                                          buffer, bufSize, docURL);
  545.   }
  546.   if (result != 0) {
  547.     if (log.IsLogging(0)) {
  548.       log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - exiting "
  549.         L"with error result " << result;
  550.       log.EndDiagnostic();
  551.     }
  552.     return result; // may return { -1, 1, 2, 3 }
  553.   }
  554.   // store buffer for reference
  555.   if (content) {
  556.     VXIbyte *tempbuf = new VXIbyte[bufSize];
  557.     if(tempbuf == NULL) {
  558.       log.LogError(202);
  559.       if( !isDefaultDoc ) DocumentParser::ReleaseBuffer(buffer);
  560.       return -1;
  561.     }
  562.     memcpy(tempbuf, buffer, bufSize);
  563.     if (size != NULL) *size = bufSize;
  564.     *content = tempbuf;
  565.   }
  566.   
  567.   // (3) Pull the document from cache.
  568.   
  569.   vxistring baseURL;
  570.   VXMLDocument doc;
  571.   if (!DocumentStorageSingleton::Instance()->Retrieve(doc, buffer, bufSize, docURL.c_str())) {
  572.       // (3.1) Set the base uri for this document, but
  573.       // ignore if it is the default doc. Note: only want to do this if
  574.       // not pulling from the cache otherwise the base is messed up
  575.       if(!isDefaultDoc) 
  576.         converter->SetBaseUri(docURL.c_str());
  577.     // (4) Not in cache; parse buffer into our VXML document representation
  578.     try {
  579.       VXIcharToXMLCh membufURL(docURL.c_str());
  580.       // Set Document level
  581.       if( isDefaults ) 
  582.         converter->SetDocumentLevel(DEFAULTS);
  583.       else if( isRootApp )
  584.         converter->SetDocumentLevel(APPLICATION);
  585.       else
  586.         converter->SetDocumentLevel(DOCUMENT);
  587.       // Parse the script
  588.   MemBufInputSource membuf(buffer, bufSize, membufURL.c_str(), false);
  589.       parser->parse(membuf);
  590.     }
  591.     catch (const XMLException & exception) {
  592.       if( !isDefaultDoc ) DocumentParser::ReleaseBuffer(buffer);
  593.       if (log.IsLogging(0)) {
  594.         XMLChToVXIchar message(exception.getMessage());
  595.         log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - XML "
  596.           L"parsing error from DOM: " << message;
  597.         log.EndDiagnostic();
  598.       }
  599.       return 4;
  600.     }
  601.     catch (const SAXParseException & exception) {
  602.       VXIString *key = NULL, *value = NULL;
  603.       if (log.LogContent(VXI_MIME_XML, buffer, bufSize, &key, &value)) 
  604.       {
  605.         vxistring temp(L"");
  606.         temp += VXIStringCStr(key);
  607.         temp += L": ";
  608.         temp += VXIStringCStr(value);
  609.         log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - buffer is saved in: "
  610.                                << temp;
  611.         log.EndDiagnostic();
  612.       }        
  613.       if (key) VXIStringDestroy(&key);
  614.       if (value) VXIStringDestroy(&value);
  615.       
  616.       if( !isDefaultDoc ) DocumentParser::ReleaseBuffer(buffer);
  617.       if (log.IsLogging(0)) {
  618.         XMLChToVXIchar sysid(exception.getSystemId());
  619.         XMLChToVXIchar message(exception.getMessage());
  620.         log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - Parse "
  621.                                << L"error in file "" 
  622.                                << sysid
  623.                                << L"", line " << exception.getLineNumber()
  624.                                << L", column " << exception.getColumnNumber()
  625.                                << L" - " 
  626.                                << message;
  627.         log.EndDiagnostic();
  628.       }
  629.       return 4;
  630.     }
  631.     // (5) Write the compiled form out to the cache.
  632.     doc = converter->GetDocument();
  633.     // Set the current uri as base uri if there isn't a "xml:base" attribute
  634.     doc.GetBaseURL(baseURL);
  635.     if( baseURL.empty() ) doc.SetBaseURL(docURL);
  636.     
  637.     // store default language
  638.     if( isDefaults ) {
  639.       vxistring dlang;
  640.       converter->GetDefaultLang(dlang);
  641.       doc.SetDefaultLang(dlang);
  642.     }        
  643.     // Put into memory cache
  644.     DocumentStorageSingleton::Instance()->Store(doc, buffer, bufSize, docURL.c_str());
  645.   }
  646.   else {
  647.     // The document is already in the memory cache
  648.     // Need to set the base uri
  649.     converter->RestoreBaseURLFromCache(doc);
  650.     // Restore default language
  651.     if( isDefaults ) {
  652.       converter->RestoreDefaultLangFromCache(doc);
  653.     }
  654.   }
  655.   if( !isDefaultDoc ) DocumentParser::ReleaseBuffer(buffer);
  656.   // (6) Parse was successful, process document.  We want only the top level
  657.   // <vxml> node.
  658.   const VXMLElement root = doc.GetRoot();
  659.   VXMLElementType nodeName = root.GetName();
  660.   // If we're looking for the defaults, we can exit early.
  661.   if (isDefaults && nodeName == DEFAULTS_ROOT) {
  662.     log.LogDiagnostic(2, L"DocumentParser::FetchDocument(): Default document - success");
  663.     document = doc;
  664.     return 0;
  665.   }
  666.   else if (nodeName != NODE_VXML) {
  667.     document = VXMLDocument();
  668.     if (log.IsLogging(0)) {
  669.       log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - unable to "
  670.         L"find " << NODE_VXML << L" in document.";
  671.       log.EndDiagnostic();
  672.     }
  673.     return 4;
  674.   }
  675.   vxistring temp;
  676.   // If the properties map is NULL, don't bother with the remaining settings
  677.   if (docProperties.GetValue() != NULL) {
  678.     // Retrieve the properties and put them into the map.
  679.     VXIString * str = NULL;
  680.     temp = docURL;
  681.     str = VXIStringCreate(temp.c_str());
  682.     if (str == NULL) 
  683.       throw VXIException::OutOfMemory();
  684.     VXIMapSetProperty(docProperties.GetValue(), PropertyList::AbsoluteURI,
  685.                       reinterpret_cast<VXIValue *>(str));
  686.     str = VXIStringCreate(converter->GetBaseUri().empty() ? L"" : 
  687.                           converter->GetBaseUri().c_str());
  688.     
  689.     if (str == NULL)
  690.       throw VXIException::OutOfMemory();
  691.     VXIMapSetProperty(docProperties.GetValue(), PropertyList::BaseURI,
  692.                       reinterpret_cast<VXIValue *>(str));
  693. // store encoding
  694.     str = VXIStringCreate(encoding.empty() ? L"UTF-8" : encoding.c_str());
  695.     if (str == NULL)
  696.       throw VXIException::OutOfMemory();
  697.     VXIMapSetProperty(docProperties.GetValue(), PropertyList::SourceEncoding,
  698.                       reinterpret_cast<VXIValue *>(str));
  699. // store xml:lang
  700. if (root.GetAttribute(ATTRIBUTE_XMLLANG, temp)) {
  701.       str = VXIStringCreate(temp.c_str());
  702.       if (str == NULL)
  703.         throw VXIException::OutOfMemory();
  704.       VXIMapSetProperty(docProperties.GetValue(), PropertyList::Language,
  705.                         reinterpret_cast<VXIValue *>(str));
  706.     }
  707.   }
  708.   log.LogDiagnostic(2, L"DocumentParser::FetchDocument(): VXML document - success");
  709.   document = doc;
  710.   return 0;
  711. }
  712. int DocumentParser::FetchContent(const VXIchar * uri,
  713.                                  const VXIMapHolder & properties,
  714.                                  VXIMapHolder & fetchInfo,
  715.                                  VXIinetInterface * inet,
  716.                                  SimpleLogger & log,
  717.                                  const vxistring & encoding,
  718.                                  vxistring & content)
  719. {
  720.   const VXIbyte * buffer;
  721.   VXIulong bufSize;
  722.   vxistring docURL;
  723.   // (1) Retrieve the URI.
  724.   switch (DocumentParser::FetchBuffer(uri, properties, fetchInfo, inet, log,
  725.                                       buffer, bufSize, docURL)) {
  726.   case -1: // Out of memory?
  727.     return -1;
  728.   case  0: // Success
  729.     break;
  730.   case  2: // Unable to open URI
  731.     return 2;
  732.   case  3: // Unable to read from URI
  733.     return 3;
  734.   case  1: // Invalid parameter
  735.   default:
  736.     return 1;
  737.   }
  738.   // (2) Create a transcoder for the requested type.
  739.   VXIcharToXMLCh encName(encoding.c_str());
  740.   XMLTransService::Codes failReason;
  741.   XMLTranscoder* transcoder = 
  742.       XMLPlatformUtils::fgTransService->makeNewTranscoderFor(encName.c_str(),
  743.                                                              failReason,
  744.                                                              8*1064
  745. #if _XERCES_VERSION <= 20200                                                             
  746.                                                               );
  747. #else
  748.                                                              ,XMLPlatformUtils::fgMemoryManager);
  749. #endif
  750.   if (transcoder == NULL) return 4;
  751.   // (3) Allocate memory for the conversion.
  752.   XMLCh * convertedString = new XMLCh[bufSize+1];
  753.   unsigned char* charSizes = new unsigned char[bufSize];
  754.   if (convertedString == NULL || charSizes == NULL) {
  755.     delete[] convertedString;
  756.     delete[] charSizes;
  757.     return -1;
  758.   }
  759.   // (4) Transcode the values into our string.
  760.   unsigned int bytesEaten;
  761.   unsigned int charsDone = transcoder->transcodeFrom(buffer, bufSize,
  762.                                                      convertedString, bufSize,
  763.                                                      bytesEaten, charSizes);
  764.   // (5) Finally convert from XMLCh to VXIchar.
  765.   convertedString[charsDone] = '';  // Add terminator. 
  766.   XMLChToVXIchar result(convertedString);
  767.   // (6) Done.  Release memory.
  768.   content = result.c_str();
  769.   delete[] convertedString;
  770.   delete[] charSizes;
  771.   DocumentParser::ReleaseBuffer(buffer);
  772.   return 0;
  773. }
  774. int DocumentParser::FetchXML(const VXIchar * uri, const VXIMapHolder & fetchobj,
  775.                       VXIMapHolder & fetchStatus, 
  776.   VXIinetInterface * inet, SimpleLogger & log,
  777.   DOMDocument **doc )
  778. {
  779.   if (log.IsLogging(2)) {
  780.     log.StartDiagnostic(2) << L"DocumentParser::FetchXML(" << uri << L")";
  781.     log.EndDiagnostic();
  782.   }
  783.   const VXIbyte *buffer = NULL;
  784.   VXIulong cbBuffer = 0;
  785.   vxistring docURI;
  786.   int result = DocumentParser::FetchBuffer(
  787.       uri, fetchobj, fetchStatus,
  788.       inet, log, 
  789.       buffer, cbBuffer,
  790.       docURI);
  791.   if (result != 0) {
  792.     if (log.IsLogging(0)) {
  793.       log.StartDiagnostic(0) << L"DocumentParser::FetchXML - exiting "
  794.         L"with error result " << result;
  795.       log.EndDiagnostic();
  796.     }
  797.     return result; // may return { -1, 1, 2, 3 }
  798.   }
  799.   // Instantiate the DOM parser.
  800.   static const XMLCh gLS[] = { chLatin_L, chLatin_S, chNull };
  801.   DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(gLS);
  802.   xercesc::DOMBuilder *domParser = ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
  803.   domParser->setFeature(XMLUni::fgDOMNamespaces, true);
  804.   domParser->setFeature(XMLUni::fgXercesSchema, true);
  805.   domParser->setFeature(XMLUni::fgDOMValidation, true);
  806.   domParser->setFeature(XMLUni::fgDOMValidateIfSchema, true);
  807.   domParser->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
  808.   domParser->setErrorHandler(new DOMErrorReporter());
  809.   // This is a big fat hack.
  810.   // The Xerces DOMBuilder owns the DOMDocument after parsing.  Until a
  811.   // good way to make a copy of the DOMDocument is found, we're going to
  812.   // use a DOMParser per DOMDocument.  There may already be a way to 
  813.   // copy a DOMDocument, and we just haven't seen it... if so then
  814.   // shame on us.
  815.   domParsers.push_back(domParser);
  816.   try
  817.   {
  818.     // reset document pool
  819.     domParser->resetDocumentPool();
  820. VXIcharToXMLCh membufURL(uri);
  821.     MemBufInputSource membuf(buffer, cbBuffer, membufURL.c_str(), false);
  822.     Wrapper4InputSource domis( &membuf, false );
  823.     *doc = domParser->parse(domis);
  824.     result = 0;
  825.   }
  826.   catch (const XMLException& exception)
  827.   {
  828.     *doc = NULL;
  829.     
  830.     XMLChToVXIchar message(exception.getMessage());
  831.     log.StartDiagnostic(0) << L"DocumentParser::FetchXML - XML parsing "
  832.       L"error from DOM: " << message;
  833.     log.EndDiagnostic();
  834.     log.LogError(999, SimpleLogger::MESSAGE, L"unable to load XML");
  835.     result = 4;
  836.   }
  837.   catch (const DOMException& exception)
  838.   {
  839.     *doc = NULL;
  840.     XMLChToVXIchar message(exception.getMessage());
  841.     log.StartDiagnostic(0) << L"DocumentParser::FetchXML - Parse error: "
  842.                            << message;
  843.     log.EndDiagnostic();
  844.     log.LogError(999, SimpleLogger::MESSAGE, L"unable to load XML");
  845.     result = 4;
  846.   }
  847.   catch( VXIDOMException &exception )
  848.   {
  849.     *doc = NULL;
  850.     log.StartDiagnostic(0) << L"DocumentParser::FetchXML - Parse error: "
  851.       << L"URI=" << exception.getURI()
  852.       << L", line=" << exception.getLine()
  853.       << L", col=" << exception.getColumn()
  854.       << L", Message=" << exception.getMessage();
  855.     log.EndDiagnostic();
  856.     result = 4;
  857.   }
  858.   catch (...)
  859.   {
  860.     *doc = NULL;
  861.     log.StartDiagnostic(0) << L"DocumentParser::FetchXML - Unknown Parse error";
  862.     log.EndDiagnostic();
  863.     log.LogError(999, SimpleLogger::MESSAGE, L"unable to load XML");
  864.     result = 4;
  865.   }
  866.   DocumentParser::ReleaseBuffer(buffer);
  867.   return result;
  868. }
  869. void DocumentParser::XMLDecl(
  870.   const XMLCh* const    versionStr,
  871.   const XMLCh* const    encodingStr,
  872.   const XMLCh* const    standaloneStr,
  873.   const XMLCh* const    autoEncodingStr )
  874. {
  875.   XMLChToVXIchar enc(autoEncodingStr);
  876.   encoding = enc.c_str();
  877. }