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

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. /***********************************************************************
  23.  *
  24.  * This is largely a wrapper around the VXIjsi interface.  The limited
  25.  * responsibilities of this layer include:
  26.  *
  27.  *   (1) storing the VXIjsiContext and current scope name;
  28.  *   (2) generating error.semantic exceptions for ECMAScript failures;
  29.  *   (3) converting vxistring's to const wchar_t *;
  30.  *   (4) converting VXIValue types.
  31.  *
  32.  ***********************************************************************/
  33. #include "Scripter.hpp"
  34. #include "CommonExceptions.hpp"
  35. #include "VXML.h"
  36. #include "VXIjsi.h"
  37. #include <sstream>
  38. // This is a simple conversion tool from VXIString -> vxistring.
  39. static vxistring toString(const VXIString * s)
  40. {
  41.   if (s == NULL) return L"";
  42.   const VXIchar * temp = VXIStringCStr(s);
  43.   if (temp == NULL) return L"";
  44.   return temp;
  45. }
  46. /*****************************************************************************
  47.  * Constructor/Destructor - here is where the VXIjsiContext is managed.
  48.  *****************************************************************************/
  49. Scripter::Scripter(VXIjsiInterface *jsiapi) : jsi_api(jsiapi)
  50. {
  51.   if (jsi_api == NULL)
  52.     maybe_throw_js_error(VXIjsi_RESULT_INVALID_ARGUMENT);
  53.   maybe_throw_js_error(jsi_api->CreateContext(jsi_api, &jsi_context));
  54. }
  55. Scripter::~Scripter()
  56. {
  57.   VXIjsiResult err = jsi_api->DestroyContext(jsi_api, &jsi_context);
  58. }
  59. /*****************************************************************************
  60.  * Raise javascript exeception on error
  61.  ****************************************************************************/
  62. void Scripter::maybe_throw_js_error(int err, const VXIchar *script) const
  63. {
  64.   switch (err) {
  65.   case VXIjsi_RESULT_SUCCESS:
  66.     return;
  67.   case VXIjsi_RESULT_FAILURE:           // Normal failure
  68.   case VXIjsi_RESULT_NON_FATAL_ERROR:   // Non-fatal non-specific error
  69.   case VXIjsi_RESULT_SYNTAX_ERROR:      // JavaScript syntax error
  70.   case VXIjsi_RESULT_SCRIPT_EXCEPTION:  // JavaScript exception thrown
  71.   case VXIjsi_RESULT_SECURITY_VIOLATION:// JavaScript security violation
  72.   {
  73.     vxistring msg;
  74.     const VXIMap *error = jsi_api->GetLastError(jsi_api, jsi_context);
  75.     if (error) {
  76.       const VXIString *s = reinterpret_cast<const VXIString *>(VXIMapGetProperty(error, L"message"));
  77.       if (s) msg = VXIStringCStr(s);
  78.     }
  79.     throw VXIException::InterpreterEvent(EV_ERROR_ECMASCRIPT, msg);
  80.   }
  81.   default:
  82.     throw VXIException::JavaScriptError();
  83.   }
  84. }
  85. /*****************************************************************************
  86.  * Wrappers around basic JSI interface. VXI only call JavaScript through here.
  87.  *****************************************************************************/
  88. void Scripter::MakeVar(const vxistring & name, const vxistring & expr)
  89. {
  90.   if (expr.empty()) {
  91.     EvalScript(L"var " + name);
  92.     return;
  93.   }
  94.   VXIjsiResult err = jsi_api->CreateVarExpr(jsi_api, jsi_context,
  95.                                             name.c_str(), expr.c_str());
  96.   // This handles variables such as x.y which are invalid arguments.
  97.   if (err == VXIjsi_RESULT_INVALID_ARGUMENT && !name.empty())
  98.     err = VXIjsi_RESULT_FAILURE;
  99.   maybe_throw_js_error(err);
  100. }
  101. void Scripter::MakeVar(const vxistring & name, const VXIValue * value)
  102. {
  103.   VXIjsiResult err = jsi_api->CreateVarValue(jsi_api, jsi_context,
  104.                                              name.c_str(), value);
  105.   // This handles variables such as x.y which are invalid arguments.
  106.   if (err == VXIjsi_RESULT_INVALID_ARGUMENT && !name.empty())
  107.     err = VXIjsi_RESULT_FAILURE;
  108.   maybe_throw_js_error(err);
  109. }
  110. void Scripter::MakeVar(const vxistring & name, xercesc::DOMDocument *doc)
  111. {
  112.   VXIPtr *ptr = VXIPtrCreate(doc);
  113.   VXIjsiResult err = jsi_api->CreateVarDOM(jsi_api, jsi_context,
  114.                                          name.c_str(), ptr);
  115.   VXIPtrDestroy(&ptr);
  116.   maybe_throw_js_error(err);
  117. }
  118. void Scripter::SetVar(const vxistring & name, const vxistring & expr)
  119. {
  120.   VXIjsiResult err = jsi_api->SetVarExpr(jsi_api, jsi_context,
  121.                                          name.c_str(), expr.c_str());
  122.   maybe_throw_js_error(err, name.c_str());
  123. }
  124. void Scripter::SetVarReadOnly(const vxistring & name)
  125. {
  126.   VXIjsiResult err = jsi_api->SetReadOnly(jsi_api, jsi_context,
  127.                                           name.c_str());
  128.   maybe_throw_js_error(err);
  129. }
  130. void Scripter::ClearVar(const vxistring & name)
  131. {
  132.   VXIjsiResult err = jsi_api->SetVarExpr(jsi_api, jsi_context,
  133.                                          name.c_str(), L"undefined");
  134.   maybe_throw_js_error(err);
  135. }
  136. void Scripter::SetValue(const vxistring & var, const VXIValue * value)
  137. {
  138.   VXIjsiResult err = jsi_api->SetVarValue(jsi_api, jsi_context,
  139.                                           var.c_str(), value);
  140.   maybe_throw_js_error(err);
  141. }
  142. VXIValue * Scripter::GetValue(const vxistring & name) const
  143. {
  144.   VXIValue* val = NULL;
  145.   VXIjsiResult err = jsi_api->GetVar(jsi_api, jsi_context, name.c_str(), &val);
  146.   switch (err) {
  147.   case VXIjsi_RESULT_FAILURE:         // ECMAScript type Null
  148.   case VXIjsi_RESULT_NON_FATAL_ERROR: // ECMAScript type Undefined
  149.   case VXIjsi_RESULT_SUCCESS:
  150.     break;
  151.   default:
  152.     maybe_throw_js_error(err);
  153.   }
  154.   return val;
  155. }
  156. void Scripter::SetString(const vxistring & name, const vxistring & val)
  157. {
  158.   vxistring line = val;
  159.   // Normalize whitespace to ' '
  160.   for (unsigned int i = 0; i < line.length(); ++i) {
  161.     VXIchar c = line[i];
  162.     if (c == 'n' || c == 'r' || c == 't') line[i] = ' ';
  163.   }
  164.   // Escape the ' characters.
  165.   const VXIchar APOSTROPHE = ''';
  166.   const VXIchar * const SLASH = L"\";
  167.   vxistring::size_type pos = line.find(APOSTROPHE);
  168.   if (pos != vxistring::npos) {
  169.     unsigned int size = line.length();
  170.     do {
  171.       line.insert(pos, SLASH);    // Convert ' -> '
  172.       if (++pos == size) break;   // Stop if last character was replaced.
  173.       ++size;                     // Update the size.
  174.       pos = line.find(APOSTROPHE, pos + 1);
  175.     } while (pos != vxistring::npos);
  176.   }
  177.   // Pass the expression to ECMAScript.
  178.   line = name + L" = '" + line + L"';";
  179.   VXIjsiResult err = jsi_api->Eval(jsi_api, jsi_context, line.c_str(), NULL);
  180.   maybe_throw_js_error(err);
  181. }
  182. void Scripter::PushScope(const vxistring & name, bool alias)
  183. {
  184.   VXIjsiScopeAttr scopeAttr 
  185.     = alias ? VXIjsi_ALIAS_SCOPE : VXIjsi_NATIVE_SCOPE;
  186.   VXIjsiResult err = jsi_api->PushScope(jsi_api, jsi_context, name.c_str(),
  187.                                         scopeAttr);
  188.   if (err == VXIjsi_RESULT_SUCCESS)
  189.     scopeStack.push_back(name);
  190.   maybe_throw_js_error(err);
  191. }
  192. void Scripter::PopScope()
  193. {
  194.   VXIjsiResult err = jsi_api->PopScope(jsi_api, jsi_context);
  195.   if (err == VXIjsi_RESULT_SUCCESS)
  196.     scopeStack.pop_back();
  197.   maybe_throw_js_error(err);
  198. }
  199. bool Scripter::CurrentScope(const vxistring & name) const
  200. {
  201.   return name == scopeStack.back();
  202. }
  203. bool Scripter::IsVarDefined(const vxistring & name)
  204. {
  205.   switch (jsi_api->CheckVar(jsi_api, jsi_context, name.c_str())) {
  206.   case VXIjsi_RESULT_SUCCESS:
  207.     return true;
  208.   case VXIjsi_RESULT_NON_FATAL_ERROR:    
  209.   case VXIjsi_RESULT_FAILURE:
  210.     return false;
  211.   default:
  212.     throw VXIException::JavaScriptError();
  213.   }
  214.   // We should never get here.
  215.   return false;
  216. }
  217. bool Scripter::IsVarDeclared(const vxistring & name)
  218. {
  219.   switch (jsi_api->CheckVar(jsi_api, jsi_context, name.c_str())) {
  220.   case VXIjsi_RESULT_FAILURE:
  221.   case VXIjsi_RESULT_SUCCESS:
  222.     return true;
  223.   case VXIjsi_RESULT_NON_FATAL_ERROR:    
  224.     return false;
  225.   default:
  226.     throw VXIException::JavaScriptError();
  227.   }
  228.   // We should never get here.
  229.   return false;
  230. }
  231. bool Scripter::TestCondition(const vxistring & script)
  232. {
  233.   return (EvalScriptToInt(script) != 0);
  234. }
  235. VXIint Scripter::EvalScriptToInt(const vxistring & expr)
  236. {
  237.   VXIValue* val = NULL;
  238.   VXIjsiResult err = jsi_api->Eval(jsi_api, jsi_context, expr.c_str(), &val);
  239.   VXIint result;
  240.   if (err == VXIjsi_RESULT_SUCCESS) {
  241.     switch (VXIValueGetType(val)) {
  242.     case VALUE_STRING: {
  243.       const VXIchar* s = 
  244.             VXIStringCStr(reinterpret_cast<const VXIString*>(val));
  245.       result = ((s != NULL && *s != L'') ? 1 : 0);      
  246.     } break;
  247.     case VALUE_BOOLEAN:
  248.       result = VXIint(VXIBooleanValue(reinterpret_cast<const VXIBoolean*>(val)));
  249.       break;
  250.     case VALUE_INTEGER:
  251.       result = VXIIntegerValue(reinterpret_cast<const VXIInteger*>(val));
  252.       break;
  253.     case VALUE_FLOAT: {
  254.       // Convert float down to VXIint.
  255.       // For GCC 3.2.2, convert float to int not correctly produce result
  256.       // therefore we must cast to unsigned long first
  257. #if defined(__GNUC__) && ((__GNUC__ >= 3) && (__GLIBCPP__ >= 20030205))
  258.       result = VXIint(VXIulong(VXIFloatValue(reinterpret_cast<const VXIFloat*>(val))));
  259. #else
  260.       result = VXIint(VXIFloatValue(reinterpret_cast<const VXIFloat*>(val)));
  261. #endif
  262.     } break;
  263. #if (VXI_CURRENT_VERSION >= 0x00030000)
  264.     case VALUE_DOUBLE: {
  265.       // Convert double down to VXIint.
  266.       // For GCC 3.2.2, convert double to int not correctly produce result
  267.       // therefore we must cast to unsigned long first
  268. #if defined(__GNUC__) && ((__GNUC__ >= 3) && (__GLIBCPP__ >= 20030205))
  269.       result = VXIint(VXIulong(VXIDoubleValue(reinterpret_cast<const VXIDouble*>(val))));
  270. #else
  271.       result = VXIint(VXIDoubleValue(reinterpret_cast<const VXIDouble*>(val)));
  272. #endif
  273.     } break;
  274.   case VALUE_ULONG:
  275.     result = VXIint(VXIULongValue(reinterpret_cast<const VXIULong*>(val)));
  276.     break;
  277. #endif    
  278.     case VALUE_MAP: {
  279.       // if the map is not empty, return 1
  280.       result = 0;
  281.       const VXIMap* temp = reinterpret_cast<const VXIMap*>(val);
  282.       if( temp && (VXIMapNumProperties(temp) > 0) ) result = 1;
  283.     } break;
  284.     default:
  285.       err = VXIjsi_RESULT_FAILURE;
  286.       break;
  287.     }
  288.   }
  289.   VXIValueDestroy(&val);
  290.   maybe_throw_js_error(err);
  291.   return result;
  292. }
  293. void Scripter::EvalScriptToString(const vxistring & expr, vxistring & result)
  294. {
  295.   VXIValue * val = NULL;
  296.   VXIjsiResult err = jsi_api->Eval(jsi_api, jsi_context, expr.c_str(), &val);
  297.   std::basic_ostringstream<wchar_t> os;
  298.   if (err == VXIjsi_RESULT_SUCCESS) {
  299.     switch (VXIValueGetType(val)) {
  300.     case VALUE_BOOLEAN:
  301.       if(VXIBooleanValue(reinterpret_cast<const VXIBoolean*>(val)) == TRUE)
  302.         os << L"true";
  303.       else
  304.         os << L"false";
  305.       break;
  306.     case VALUE_INTEGER:
  307.       os << VXIIntegerValue(reinterpret_cast<const VXIInteger*>(val));
  308.       break;
  309.     case VALUE_FLOAT:
  310.       os << VXIFloatValue(reinterpret_cast<const VXIFloat*>(val));
  311.       break;
  312. #if (VXI_CURRENT_VERSION >= 0x00030000)
  313.     case VALUE_DOUBLE:
  314.       os << VXIDoubleValue(reinterpret_cast<const VXIDouble*>(val));
  315.       break;
  316.     case VALUE_ULONG:
  317.       os << VXIULongValue(reinterpret_cast<const VXIULong*>(val));
  318.       break;
  319. #endif      
  320.     case VALUE_STRING:
  321.       std::fixed(os);
  322.       os << VXIStringCStr(reinterpret_cast<const VXIString *>(val));
  323.       break;
  324.     default:
  325.       err = VXIjsi_RESULT_FAILURE;
  326.       break;
  327.     }
  328.   }
  329.   VXIValueDestroy(&val);
  330.   result = os.str();
  331.   maybe_throw_js_error(err);
  332. }
  333. void Scripter::EvalScript(const vxistring & expr)
  334. {
  335.   VXIjsiResult err = jsi_api->Eval(jsi_api, jsi_context, expr.c_str(), NULL);
  336.   maybe_throw_js_error(err);
  337. }
  338. VXIValue * Scripter::EvalScriptToValue(const vxistring & expr)
  339. {
  340.   VXIValue* val = NULL;
  341.   VXIjsiResult err = jsi_api->Eval(jsi_api, jsi_context, expr.c_str(), &val);
  342.   if (err == VXIjsi_RESULT_FAILURE) return NULL;  // from ECMAScript 'null'
  343.   maybe_throw_js_error(err);
  344.   return val;
  345. }