void UnityLog::Init() { uLogger.registerLogger(); debuglogger.registerLogger(); InitializeCriticalSection(&CriticalSection); }
void GrammarManager::BuildOptionGrammar(const SimpleLogger & log, const VXMLElement & doc, bool isDTMF, vxistring & gram) { log.LogDiagnostic(2, L"GrammarManager::BuildOptionGrammar()"); gram = L""; // Clear grammar string bool firstTime = true; for (VXMLNodeIterator it(doc); it; ++it) { VXMLNode child = *it; if (child.GetType() != VXMLNode::Type_VXMLElement) continue; VXMLElement & domElem = reinterpret_cast<VXMLElement &>(child); if (domElem.GetName() != NODE_OPTION) continue; vxistring text; vxistring value; domElem.GetAttribute(ATTRIBUTE_VALUE, value); if (isDTMF) { domElem.GetAttribute(ATTRIBUTE_DTMF, text); if (value.empty()) GrammarManager::GetEnclosedText(log, domElem, value); } else { GrammarManager::GetEnclosedText(log, domElem, text); } if (text.empty()) continue; if (!firstTime) gram += L" | "; gram += text; if (!value.empty()) { gram += L" {"; gram += value; gram += L"}"; } firstTime = false; } log.LogDiagnostic(2, L"GrammarManager::BuildOptionGrammar - end"); }
bool GrammarManager::GetEnclosedText(const SimpleLogger & log, const VXMLElement & doc, vxistring & str) { log.LogDiagnostic(2, L"GrammarManager::GetEnclosedText()"); // Clear the result first... str = L""; for (VXMLNodeIterator it(doc); it; ++it) { VXMLNode child = *it; if (child.GetType() == VXMLNode::Type_VXMLContent) { VXMLContent & content = reinterpret_cast<VXMLContent &>(child); vxistring temp = content.GetValue(); while (temp.length() > 0) { // Strip off any empty characters from beginning VXIchar c = temp[0]; if (c == ' ' || c == '\r' || c == '\n' || c == '\t') temp.erase(0, 1); else { str += temp; break; } } } } if (!str.empty()) { // Strip off any trailing whitespace while (str.length() > 0) { unsigned int len = str.length(); VXIchar c = str[len - 1]; if (c == ' ' || c == '\r' || c == '\n' || c == '\t') str.erase(len - 1, 1); else break; } } log.LogDiagnostic(2, L"GrammarManager::GetEnclosedText - end"); return !str.empty(); }
// -2: Internal error int DocumentParser::FetchDocument(const VXIchar * url, const VXIMapHolder & properties, VXIinetInterface * inet, VXIcacheInterface * cache, SimpleLogger & log, VXMLDocument & document, VXIMapHolder & docProperties, bool isDefaults, bool isRootApp, VXIbyte **content, VXIulong *size) { int result; int path_only = 0; VXMLDocument *cached_parse_tree = NULL; if (log.IsLogging(2)) { log.StartDiagnostic(2) << L"DocumentParser::FetchDocument(" << url << L")"; log.EndDiagnostic(); } // (1) Load the VXML DTD for validation. This will override an externally // specified DTD if the user provides a link. try { if (isDefaults) { MemBufInputSource membuf( VALIDATOR_DATA + DUMMY_VXML_DEFAULTS_DOC, DUMMY_VXML_DEFAULTS_DOC_SIZE, "vxml 1.0 defaults"); parser->parse(membuf); converter->ResetDocument(); // Throw this document away. } if (!isDefaults && !loadedVXML20) { // Preload the VXML 2.1 schema. VXIcharToXMLCh name(L"http://www.w3.org/TR/voicexml21/vxml.xsd"); LockLoadGrammar(); parser->loadGrammar(name.c_str(), Grammar::SchemaGrammarType, true); // Reuse cached grammars if available. parser->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true); UnlockLoadGrammar(); loadedVXML20 = true; } } catch (const XMLException & exception) { if (!isDefaults && !loadedVXML20) UnlockLoadGrammar(); XMLChToVXIchar message(exception.getMessage()); log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - XML parsing " L"error from DOM: " << message; log.EndDiagnostic(); log.LogError(999, SimpleLogger::MESSAGE, L"unable to load VXML DTD"); return 4; } catch (const SAXParseException & exception) { if (!isDefaults && !loadedVXML20) UnlockLoadGrammar(); XMLChToVXIchar sysid(exception.getSystemId()); XMLChToVXIchar message(exception.getMessage()); log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - Parse error " << L"in file \"" << sysid << L"\", line " << exception.getLineNumber() << L", column " << exception.getColumnNumber() << L" - " << message; log.EndDiagnostic(); log.LogError(999, SimpleLogger::MESSAGE, L"unable to load VXML DTD"); return 4; } catch (...) { if (!isDefaults && !loadedVXML20) UnlockLoadGrammar(); log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - Unknown Parse error"; log.EndDiagnostic(); log.LogError(999, SimpleLogger::MESSAGE, L"unable to load VXML DTD"); return 4; } // (2) Load the url's content into memory. const VXIbyte * buffer = NULL; VXIulong bufSize = 0; vxistring docURL; bool isDefaultDoc = false; if (isDefaults && wcslen(url) == 0) { buffer = VALIDATOR_DATA + VXML_DEFAULTS; bufSize = VXML_DEFAULTS_SIZE; docURL = L"builtin defaults"; result = 0; isDefaultDoc = true; } else { path_only = 1; result = DocumentParser::FetchBuffer (url, properties, docProperties, inet, log, buffer, bufSize, docURL, 1, &cached_parse_tree); } if (result != 0) { if (log.IsLogging(0)) { log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - exiting " L"with error result " << result; log.EndDiagnostic(); } return result; // may return { -1, 1, 2, 3 } } // store buffer for reference if (content) { VXIbyte *tempbuf = new VXIbyte[bufSize]; if(tempbuf == NULL) { log.LogError(202); if( !isDefaultDoc ) DocumentParser::ReleaseBuffer(buffer); return -1; } if (voiceglue_loglevel() >= LOG_DEBUG) { std::ostringstream logstring; logstring << "(Copy) Allocated http_get buffer " << Pointer_to_Std_String((const void *) tempbuf) << " of size " << bufSize; voiceglue_log ((char) LOG_DEBUG, logstring); }; memcpy(tempbuf, buffer, bufSize); if (size != NULL) *size = bufSize; *content = tempbuf; } // (3) Pull the document from cache. vxistring baseURL; VXMLDocument doc; // if (!DocumentStorageSingleton::Instance()->Retrieve(doc, buffer, bufSize, docURL.c_str())) { if (cached_parse_tree == NULL) { // No cached parse tree, must perform my own parse // and return results to voiceglue perl // (3.1) Set the base uri for this document, but // ignore if it is the default doc. Note: only want to do this if // not pulling from the cache otherwise the base is messed up if(!isDefaultDoc) converter->SetBaseUri(docURL.c_str()); // (4) Not in cache; parse buffer into our VXML document representation try { VXIcharToXMLCh membufURL(docURL.c_str()); // Set Document level if( isDefaults ) converter->SetDocumentLevel(DEFAULTS); else if( isRootApp ) converter->SetDocumentLevel(APPLICATION); else converter->SetDocumentLevel(DOCUMENT); // Parse the script if (path_only) { vxistring vxi_string_path = Std_String_to_vxistring ((const char *) buffer); VXIcharToXMLCh wide_path(vxi_string_path.c_str()); LocalFileInputSource filesource(wide_path.c_str()); parser->parse(filesource); } else { MemBufInputSource membuf(buffer, bufSize, membufURL.c_str(), false); parser->parse(membuf); }; } catch (const XMLException & exception) { if( !isDefaultDoc ) DocumentParser::ReleaseBuffer(buffer); if (path_only) voiceglue_sendipcmsg ("VXMLParse 0 -\n"); if (log.IsLogging(0)) { XMLChToVXIchar message(exception.getMessage()); log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - XML " L"parsing error from DOM: " << message; log.EndDiagnostic(); } return 4; } catch (const SAXParseException & exception) { VXIString *key = NULL, *value = NULL; if (log.LogContent(VXI_MIME_XML, buffer, bufSize, &key, &value)) { vxistring temp(L""); temp += VXIStringCStr(key); temp += L": "; temp += VXIStringCStr(value); log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - buffer is saved in: " << temp; log.EndDiagnostic(); } if (key) VXIStringDestroy(&key); if (value) VXIStringDestroy(&value); if( !isDefaultDoc ) DocumentParser::ReleaseBuffer(buffer); if (path_only) voiceglue_sendipcmsg ("VXMLParse 0 -\n"); if (log.IsLogging(0)) { XMLChToVXIchar sysid(exception.getSystemId()); XMLChToVXIchar message(exception.getMessage()); log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - Parse " << L"error in file \"" << sysid << L"\", line " << exception.getLineNumber() << L", column " << exception.getColumnNumber() << L" - " << message; log.EndDiagnostic(); } return 4; } // (5) Write the parsed tree address out to the voiceglue cache doc = converter->GetDocument(); // Set the current uri as base uri if there isn't a "xml:base" attribute doc.GetBaseURL(baseURL); if( baseURL.empty() ) doc.SetBaseURL(docURL); // store default language if( isDefaults ) { vxistring dlang; converter->GetDefaultLang(dlang); doc.SetDefaultLang(dlang); } // Put into voiceglue cache as standalone persistent VXMLDocument object if (path_only) { VXMLDocument *permanent_doc = new VXMLDocument (doc); std::ostringstream ipc_msg_out; ipc_msg_out << "VXMLParse 1 " << Pointer_to_Std_String ((void *) permanent_doc) << "\n"; voiceglue_sendipcmsg (ipc_msg_out); } // DocumentStorageSingleton::Instance()->Store(doc, buffer, bufSize, docURL.c_str()); } else { // The document is already in the memory cache doc = *cached_parse_tree; // Need to set the base uri converter->RestoreBaseURLFromCache(doc); // Restore default language if( isDefaults ) { converter->RestoreDefaultLangFromCache(doc); } } if( !isDefaultDoc ) DocumentParser::ReleaseBuffer(buffer); // (6) Parse was successful, process document. We want only the top level // <vxml> node. const VXMLElement root = doc.GetRoot(); VXMLElementType nodeName = root.GetName(); // If we're looking for the defaults, we can exit early. if (isDefaults && nodeName == DEFAULTS_ROOT) { log.LogDiagnostic(2, L"DocumentParser::FetchDocument(): Default document - success"); document = doc; return 0; } else if (nodeName != NODE_VXML) { document = VXMLDocument(); if (log.IsLogging(0)) { log.StartDiagnostic(0) << L"DocumentParser::FetchDocument - unable to " L"find " << NODE_VXML << L" in document."; log.EndDiagnostic(); } return 4; } vxistring temp; // If the properties map is NULL, don't bother with the remaining settings if (docProperties.GetValue() != NULL) { // Retrieve the properties and put them into the map. VXIString * str = NULL; temp = docURL; str = VXIStringCreate(temp.c_str()); if (str == NULL) throw VXIException::OutOfMemory(); VXIMapSetProperty(docProperties.GetValue(), PropertyList::AbsoluteURI, reinterpret_cast<VXIValue *>(str)); str = VXIStringCreate(converter->GetBaseUri().empty() ? L"" : converter->GetBaseUri().c_str()); if (str == NULL) throw VXIException::OutOfMemory(); VXIMapSetProperty(docProperties.GetValue(), PropertyList::BaseURI, reinterpret_cast<VXIValue *>(str)); // store encoding str = VXIStringCreate(encoding.empty() ? L"UTF-8" : encoding.c_str()); if (str == NULL) throw VXIException::OutOfMemory(); VXIMapSetProperty(docProperties.GetValue(), PropertyList::SourceEncoding, reinterpret_cast<VXIValue *>(str)); // store xml:lang if (root.GetAttribute(ATTRIBUTE_XMLLANG, temp)) { str = VXIStringCreate(temp.c_str()); if (str == NULL) throw VXIException::OutOfMemory(); VXIMapSetProperty(docProperties.GetValue(), PropertyList::Language, reinterpret_cast<VXIValue *>(str)); } } log.LogDiagnostic(2, L"DocumentParser::FetchDocument(): VXML document - success"); document = doc; return 0; }
// 1: Invalid parameter // 2: Unable to open URL // 3: Unable to read from URL int DocumentParser::FetchBuffer(const VXIchar * url, const VXIMapHolder & properties, VXIMapHolder & streamInfo, VXIinetInterface * inet, SimpleLogger & log, const VXIbyte * & result, VXIulong & read, vxistring & docURL, int parseVXMLDocument, VXMLDocument * * document) { if (log.IsLogging(2)) { log.StartDiagnostic(2) << L"DocumentParser::FetchBuffer(" << url << L", " << properties.GetValue() << L")"; log.EndDiagnostic(); } // Set url for error report log.SetUri( url ? url : L"NONE" ); if (inet == NULL || url == NULL || wcslen(url) == 0) return 1; // (1) Open URL VXIinetStream * stream; // VXIMapHolder streamInfo; if (streamInfo.GetValue() == NULL) { return -1; } VXIinetOpenMode open_mode = INET_MODE_READ; if (parseVXMLDocument) { open_mode = INET_MODE_FILE; }; if (inet->Open(inet, L"vxi", url, open_mode, 0, properties.GetValue(), streamInfo.GetValue(), &stream) != 0) { if (log.IsLogging(0)) { log.StartDiagnostic(0) << L"DocumentParser::FetchBuffer - could not " L"open URL: " << url; log.EndDiagnostic(); } return 2; } // (2) Determine document size & absolute URL const VXIValue * tempURL = NULL; tempURL = VXIMapGetProperty(streamInfo.GetValue(), INET_INFO_ABSOLUTE_NAME); if (tempURL == NULL || VXIValueGetType(tempURL) != VALUE_STRING) { inet->Close(inet, &stream); if (log.IsLogging(0)) { log.StartDiagnostic(0) << L"DocumentParser::FetchBuffer - could not " L"retrieve absolute path of document at URL: " << url; log.EndDiagnostic(); } return 2; } docURL = VXIStringCStr(reinterpret_cast<const VXIString *>(tempURL)); VXIbyte * buffer = NULL; if (parseVXMLDocument) { // Decode parse tree addr (* document) = NULL; const VXIValue* wide_parse_tree_addr = VXIMapGetProperty(streamInfo.GetValue(), INET_INFO_PARSE_TREE); std::string parse_tree_addr = VXIValue_to_Std_String (wide_parse_tree_addr); if (parse_tree_addr.length() > 2) { void *parse_tree_pointer = Std_String_to_Pointer (parse_tree_addr); if (parse_tree_pointer != NULL) { (* document) = (VXMLDocument *) parse_tree_pointer; if (voiceglue_loglevel() >= LOG_DEBUG) { std::ostringstream logstring; logstring << "Received VXMLDocument parse tree at " << Pointer_to_Std_String ((const void *) (* document)); voiceglue_log ((char) LOG_DEBUG, logstring); }; }; }; // Decode path const VXIValue* wide_path = VXIMapGetProperty(streamInfo.GetValue(), INET_INFO_LOCAL_FILE_PATH); std::string path = VXIValue_to_Std_String (wide_path); int bufSize = path.length() + 1; buffer = new VXIbyte[bufSize]; read = bufSize; if(buffer == NULL) { log.LogError(202); return -1; } memcpy (buffer, path.c_str(), bufSize); } else { // Read into memory buffer const VXIValue * tempSize = NULL; tempSize = VXIMapGetProperty(streamInfo.GetValue(), INET_INFO_SIZE_BYTES); if (tempSize == NULL || VXIValueGetType(tempSize) != VALUE_INTEGER) { inet->Close(inet, &stream); if (log.IsLogging(0)) { log.StartDiagnostic(0) << L"DocumentParser::FetchBuffer - could not " L"retrieve size of document at URL: " << url; log.EndDiagnostic(); } return 2; } VXIint32 bufSize = VXIIntegerValue(reinterpret_cast<const VXIInteger *>(tempSize)); if (bufSize < 2047) bufSize = 2047; ++bufSize; buffer = new VXIbyte[bufSize]; if(buffer == NULL) { log.LogError(202); return -1; } if (voiceglue_loglevel() >= LOG_DEBUG) { std::ostringstream logstring; logstring << "Allocated http_get buffer " << Pointer_to_Std_String((const void *) buffer) << " of size " << bufSize; voiceglue_log ((char) LOG_DEBUG, logstring); }; bool reachedEnd = false; read = 0; while (!reachedEnd) { VXIulong bytesRead = 0; switch (inet->Read(inet, buffer+read, bufSize-read, &bytesRead, stream)) { case VXIinet_RESULT_SUCCESS: read += bytesRead; break; case VXIinet_RESULT_END_OF_STREAM: read += bytesRead; reachedEnd = true; // exit while break; case VXIinet_RESULT_WOULD_BLOCK: VXItrdThreadYield(); break; default: inet->Close(inet, &stream); delete[] buffer; log.LogDiagnostic(0, L"DocumentParser::FetchBuffer - " L"could not read from URL."); return 3; } if (read == static_cast<VXIulong>(bufSize)) { // The number of bytes read exceeds the number expected. // Double the size and keep reading. VXIbyte * temp = new VXIbyte[2*bufSize]; if(temp == NULL) { log.LogError(202); delete [] buffer; if (voiceglue_loglevel() >= LOG_DEBUG) { std::ostringstream logstring; logstring << "Released http_get buffer " << Pointer_to_Std_String((const void *) buffer); voiceglue_log ((char) LOG_DEBUG, logstring); }; return -1; } if (voiceglue_loglevel() >= LOG_DEBUG) { std::ostringstream logstring; logstring << "Allocated http_get buffer " << Pointer_to_Std_String((const void *) temp) << " of size " << (2*bufSize); voiceglue_log ((char) LOG_DEBUG, logstring); }; memcpy(static_cast<void *>(temp), static_cast<void *>(buffer), bufSize * sizeof(VXIbyte)); delete[] buffer; if (voiceglue_loglevel() >= LOG_DEBUG) { std::ostringstream logstring; logstring << "Released http_get buffer " << Pointer_to_Std_String((const void *) buffer); voiceglue_log ((char) LOG_DEBUG, logstring); }; buffer = temp; bufSize *= 2; } } inet->Close(inet, &stream); }; result = buffer; log.LogDiagnostic(2, L"DocumentParser::FetchBuffer - success"); return 0; }
int DocumentParser::FetchXML(const VXIchar * uri, const VXIMapHolder & fetchobj, VXIMapHolder & fetchStatus, VXIinetInterface * inet, SimpleLogger & log, DOMDocument **doc, bool parse_doc) { if (log.IsLogging(2)) { log.StartDiagnostic(2) << L"DocumentParser::FetchXML(" << uri << L")"; log.EndDiagnostic(); } const VXIbyte *buffer = NULL; VXIulong cbBuffer = 0; vxistring docURI; int result = DocumentParser::FetchBuffer( uri, fetchobj, fetchStatus, inet, log, buffer, cbBuffer, docURI, 0, NULL); if (result != 0) { if (log.IsLogging(0)) { log.StartDiagnostic(0) << L"DocumentParser::FetchXML - exiting " L"with error result " << result; log.EndDiagnostic(); } return result; // may return { -1, 1, 2, 3 } } if (! parse_doc) { *doc = NULL; return result; }; // Instantiate the DOM parser. static const XMLCh gLS[] = { chLatin_L, chLatin_S, chNull }; DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(gLS); xercesc::DOMBuilder *domParser = ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0); domParser->setFeature(XMLUni::fgDOMNamespaces, true); domParser->setFeature(XMLUni::fgXercesSchema, true); domParser->setFeature(XMLUni::fgDOMValidation, true); domParser->setFeature(XMLUni::fgDOMValidateIfSchema, true); domParser->setFeature(XMLUni::fgXercesSchemaFullChecking, true); domParser->setErrorHandler(new DOMErrorReporter()); // This is a big fat hack. // The Xerces DOMBuilder owns the DOMDocument after parsing. Until a // good way to make a copy of the DOMDocument is found, we're going to // use a DOMParser per DOMDocument. There may already be a way to // copy a DOMDocument, and we just haven't seen it... if so then // shame on us. domParsers.push_back(domParser); try { // reset document pool domParser->resetDocumentPool(); VXIcharToXMLCh membufURL(uri); MemBufInputSource membuf(buffer, cbBuffer, membufURL.c_str(), false); Wrapper4InputSource domis( &membuf, false ); *doc = domParser->parse(domis); result = 0; } catch (const XMLException& exception) { *doc = NULL; XMLChToVXIchar message(exception.getMessage()); log.StartDiagnostic(0) << L"DocumentParser::FetchXML - XML parsing " L"error from DOM: " << message; log.EndDiagnostic(); log.LogError(999, SimpleLogger::MESSAGE, L"unable to load XML"); result = 4; } catch (const DOMException& exception) { *doc = NULL; XMLChToVXIchar message(exception.getMessage()); log.StartDiagnostic(0) << L"DocumentParser::FetchXML - Parse error: " << message; log.EndDiagnostic(); log.LogError(999, SimpleLogger::MESSAGE, L"unable to load XML"); result = 4; } catch( VXIDOMException &exception ) { *doc = NULL; log.StartDiagnostic(0) << L"DocumentParser::FetchXML - Parse error: " << L"URI=" << exception.getURI() << L", line=" << exception.getLine() << L", col=" << exception.getColumn() << L", Message=" << exception.getMessage(); log.EndDiagnostic(); result = 4; } catch (...) { *doc = NULL; log.StartDiagnostic(0) << L"DocumentParser::FetchXML - Unknown Parse error"; log.EndDiagnostic(); log.LogError(999, SimpleLogger::MESSAGE, L"unable to load XML"); result = 4; } DocumentParser::ReleaseBuffer(buffer); return result; }