Changeset 15156 for trunk


Ignore:
Timestamp:
03/26/13 17:17:52 (12 years ago)
Author:
tbretz
Message:
Implemented sendmail class (via mailx) Mail. Re-structured the exception handling to have a more clear structure for better maintainance.
Location:
trunk/FACT++/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/FACT++/src/InterpreterV8.cc

    r15150 r15156  
    146146    HandleScope handle_scope;
    147147
    148     TryCatch exception;
    149 
    150148    Handle<Function> func = Handle<Function>::Cast(args[1]);
    151149
     
    155153
    156154    Time t;
    157     while (!exception.HasCaught())
     155    while (1)
    158156    {
    159157        const Handle<Value> rc = func->Call(func, args.Length()-2, argv);
    160         if (!rc.IsEmpty() && !rc->IsUndefined())
     158        if (rc.IsEmpty())
     159            return Undefined();
     160
     161        if (!rc->IsUndefined())
    161162            return handle_scope.Close(rc);
    162163
     
    170171        usleep(1000);
    171172    }
    172 
    173     if (exception.HasCaught())
    174         return exception.ReThrow();
    175173
    176174    if (timeout<0)
     
    331329
    332330    if (args.Length()==3 && !args[2]->IsInt32() && !args[2]->IsUndefined())
    333         return ThrowException(String::New("Argument 3 not an int32 and not null."));
     331        return ThrowException(String::New("Argument 3 not an int32 and not undefined."));
    334332
    335333    // Using a Javascript function has the advantage that it is fully
     
    692690        const String::AsciiValue file(args[i]);
    693691        if (*file == NULL)
    694             return ThrowException(String::New("File name missing"));
    695 
    696         TryCatch exception;
    697         const bool rc = ExecuteFile(*file);
    698         if (exception.HasCaught())
    699         {
    700             // If this is called from the main thread, re-throw
    701             if (fThreadId==V8::GetCurrentThreadId())
    702                 return exception.ReThrow();
    703 
    704             // Otherwise, handle the exception...
    705             HandleException(exception, "include");
    706         }
    707         if (!rc)
    708         {
    709             // ...and stop the thread immediately (if this is not done,
    710             // the other threads might still proceed);
    711             V8::TerminateExecution(fThreadId);
    712             return ThrowException(Null());
    713         }
    714     }
    715 
    716     return Undefined();//Boolean::New(true);
     692            return ThrowException(String::New("File name missing."));
     693
     694        if (strlen(*file)==0)
     695            return ThrowException(String::New("File name empty."));
     696
     697        ifstream fin(*file); // izstream does not work: WHY?
     698        if (!fin)
     699            return ThrowException(String::New(errno!=0?strerror(errno):"Insufficient memory for decompression"));
     700
     701        string buffer;
     702        getline(fin, buffer, '\0');
     703
     704        if ((fin.fail() && !fin.eof()) || fin.bad())
     705            return ThrowException(String::New(strerror(errno)));
     706
     707        const Handle<Value> rc = ExecuteCode(buffer, *file);
     708        if (rc.IsEmpty())
     709            return Undefined();
     710    }
     711
     712    return Undefined();
    717713}
    718714
     
    743739    {
    744740        string buffer;
    745         if (!getline(fin, buffer, '\0'))
     741        getline(fin, buffer, '\0');
     742        if ((fin.fail() && !fin.eof()) || fin.bad())
    746743            return ThrowException(String::New(strerror(errno)));
    747744
     
    767764
    768765    return handle_scope.Close(arr);
     766}
     767
     768// ==========================================================================
     769//                                 Mail
     770// ==========================================================================
     771
     772Handle<Value> InterpreterV8::ConstructorMail(const Arguments &args)
     773{
     774    if (!args.IsConstructCall())
     775        return ThrowException(String::New("Mail must be called as constructor"));
     776
     777    HandleScope handle_scope;
     778
     779    Handle<Object> self = args.This();
     780    self->Set(String::New("send"), FunctionTemplate::New(WrapSendMail)->GetFunction(), ReadOnly);
     781    return handle_scope.Close(self);
     782}
     783
     784vector<string> InterpreterV8::ValueToArray(const Handle<Value> &val)
     785{
     786    vector<string> rc;
     787    if (val->IsString())
     788    {
     789        rc.push_back(*String::AsciiValue(val->ToString()));
     790        return rc;
     791    }
     792
     793    if (val->IsArray())
     794    {
     795        Handle<Array> arr = Handle<Array>::Cast(val);
     796        for (uint32_t i=0; i<arr->Length(); i++)
     797        {
     798            Handle<Value> obj = arr->Get(i);
     799            if (obj.IsEmpty())
     800                continue;
     801
     802            if (!obj->IsString())
     803                return vector<string>();
     804
     805            rc.push_back(*String::AsciiValue(obj->ToString()));
     806        }
     807    }
     808
     809    return rc;
     810}
     811
     812Handle<Value> InterpreterV8::FuncSendMail(const Arguments& args)
     813{
     814    HandleScope handle_scope;
     815
     816    if (args.Length()>1)
     817        return ThrowException(String::New("Only one argument allowed."));
     818
     819    if (args.Length()==1 && !args[0]->IsBoolean())
     820        return ThrowException(String::New("Argument must be a boolean."));
     821
     822    const bool block = args.Length()==0 || args[0]->BooleanValue();
     823
     824    const Handle<Value> sub = args.This()->Get(String::New("subject"));
     825    const Handle<Value> rec = args.This()->Get(String::New("recipient"));
     826    const Handle<Value> txt = args.This()->Get(String::New("text"));
     827    const Handle<Value> att = args.This()->Get(String::New("attachment"));
     828    const Handle<Value> bcc = args.This()->Get(String::New("bcc"));
     829    const Handle<Value> cc  = args.This()->Get(String::New("cc"));
     830
     831    if (sub->IsUndefined())
     832        return ThrowException(String::New("Required property 'subject' missing."));
     833
     834    const vector<string> vrec = ValueToArray(rec);
     835    const vector<string> vtxt = ValueToArray(txt);
     836    const vector<string> vatt = ValueToArray(att);
     837    const vector<string> vbcc = ValueToArray(bcc);
     838    const vector<string> vcc  = ValueToArray(cc);
     839
     840    if (vrec.size()==0)
     841        return ThrowException(String::New("Required property 'recipient' must be a string or an array of strings."));
     842    if (vtxt.size()==0)
     843        return ThrowException(String::New("Required property 'text' must be a string or an array of strings."));
     844    if (vatt.size()==0 && !att->IsUndefined())
     845        return ThrowException(String::New("Property 'attachment' must be a string or an array of strings."));
     846    if (vbcc.size()==0 && !bcc->IsUndefined())
     847        return ThrowException(String::New("Property 'bcc' must be a string or an array of strings."));
     848    if (vcc.size()==0 && !cc->IsUndefined())
     849        return ThrowException(String::New("Property 'cc' must be a string or an array of strings."));
     850
     851    if (!sub->IsString())
     852        return ThrowException(String::New("Property 'subject' must be a string."));
     853
     854    const string subject = *String::AsciiValue(sub->ToString());
     855
     856
     857    FILE *pipe = popen(("from=no-reply@fact-project.org mailx -~ "+vrec[0]).c_str(), "w");
     858    if (!pipe)
     859        return ThrowException(String::New(strerror(errno)));
     860
     861    fprintf(pipe, "%s", ("~s"+subject+"\n").c_str());
     862    for (auto it=vrec.begin()+1; it<vrec.end(); it++)
     863        fprintf(pipe, "%s", ("~t"+*it+"\n").c_str());
     864    for (auto it=vbcc.begin(); it<vbcc.end(); it++)
     865        fprintf(pipe, "%s", ("~b"+*it+"\n").c_str());
     866    for (auto it=vcc.begin(); it<vcc.end(); it++)
     867        fprintf(pipe, "%s", ("~c"+*it+"\n").c_str());
     868    for (auto it=vatt.begin(); it<vatt.end(); it++)
     869        fprintf(pipe, "%s", ("~@"+*it+"\n").c_str());  // Must not contain white spaces
     870
     871    for (auto it=vtxt.begin(); it<vtxt.end(); it++)
     872        fwrite((*it+"\n").c_str(), it->length()+1, 1, pipe);
     873
     874    fprintf(pipe, "\n---\nsent by dimctrl");
     875
     876    if (!block)
     877        return Undefined();
     878
     879    const int rc = pclose(pipe);
     880
     881    const Locker lock;
     882    return handle_scope.Close(Integer::New(WEXITSTATUS(rc)));
    769883}
    770884
     
    12751389    }
    12761390
     1391    // This hides the location of the exception, which is wanted.
    12771392    if (exception.HasCaught())
    12781393        return exception.ReThrow();
     
    19722087
    19732088    const Handle<Value> result = ExecuteCode(code);
     2089
     2090    // This hides the location of the exception in the internal code,
     2091    // which is wanted.
    19742092    if (exception.HasCaught())
    19752093        exception.ReThrow();
     
    19782096}
    19792097
    1980 Handle<Value> InterpreterV8::ExecuteCode(const string &code, const string &file, bool main)
     2098Handle<Value> InterpreterV8::ExecuteCode(const string &code, const string &file)
    19812099{
    19822100    HandleScope handle_scope;
     
    19852103    const Handle<String> origin = String::New(file.c_str());
    19862104    if (source.IsEmpty())
    1987         return Handle<Value>();
     2105        return Undefined();
    19882106
    19892107    const Handle<Script> script = Script::Compile(source, origin);
    19902108    if (script.IsEmpty())
    1991         return Handle<Value>();
    1992 
    1993     if (main && JsGetCurrentState().index!=3)
    1994         JsSetState(3);
    1995 
    1996     TryCatch exception;
    1997 
    1998     const Handle<Value> result = script->Run();
    1999     if (exception.HasCaught())
    2000     {
    2001         if (file=="internal" || (fThreadId==V8::GetCurrentThreadId() && !main))
    2002             return exception.ReThrow();
    2003 
    2004         HandleException(exception, "code");
    2005         return Handle<Value>();
    2006     }
     2109        return Undefined();
     2110
     2111    //if (main && JsGetCurrentState().index!=3)
     2112    //    JsSetState(3);
     2113
     2114    const Handle<Value> rc = script->Run();
     2115    if (rc.IsEmpty())
     2116        return Undefined();
    20072117
    20082118    // If all went well and the result wasn't undefined then print
    20092119    // the returned value.
    2010     if (!result.IsEmpty() && !result->IsUndefined() && file!="internal")
    2011         JsResult(*String::AsciiValue(result));
    2012 
    2013     return handle_scope.Close(result);
    2014 }
    2015 
    2016 bool InterpreterV8::ExecuteFile(const string &name, bool main)
    2017 {
    2018     ifstream fin(name.c_str());
    2019     if (!fin)
    2020     {
    2021         JsException("Error - Could not open file '"+name+"'");
    2022         return false;
    2023     }
    2024 
    2025     string buffer;
    2026     if (!getline(fin, buffer, '\0'))
    2027         return true;
    2028 
    2029     if (fin.fail())
    2030     {
    2031         JsException("Error - reading file.");
    2032         return false;
    2033     }
    2034 
    2035     return !ExecuteCode(buffer, name, main).IsEmpty();
    2036 }
    2037 
    2038 bool InterpreterV8::ExecuteConsole()
    2039 {
    2040     // Just necessray for the Handle<Script>
    2041     const HandleScope handle_scope;
    2042 
    2043     // A void script doing nothing than making sure that some JavaScript is executed
    2044     const Handle<Script> catcher = Script::Compile(String::New(";"), String::New(""));
    2045 
    2046     // Unlocking is necessary for the preemption to work
    2047     const Unlocker global_unlock;
    2048 
     2120    if (!rc->IsUndefined() && file!="internal")
     2121        JsResult(*String::AsciiValue(rc));
     2122
     2123    return handle_scope.Close(rc);
     2124}
     2125
     2126void InterpreterV8::ExecuteConsole()
     2127{
    20492128    JsSetState(3);
    20502129
     
    20572136    while (1)
    20582137    {
     2138        // Create a local handle scope so that left-overs from single
     2139        // console inputs will not fill up the memory
     2140        const HandleScope handle_scope;
     2141
     2142        // Unlocking is necessary for the preemption to work
     2143        const Unlocker global_unlock;
     2144
    20592145        const string buffer = Tools::Trim(Readline::StaticPrompt(command.empty() ? "JS> " : " \\> "));
    20602146        if (buffer==".q")
     
    20822168        const Locker lock;
    20832169
    2084         // Dump all pending exceptions. This is mainly to catch the 'null' exception
    2085         // thrown if a running JavaScript should be terminated from somewhere.
    2086         while (1)
    2087         {
    2088             TryCatch exception;
    2089             catcher->Run();
    2090             if (!exception.HasCaught())
    2091                 break;
    2092         }
    2093 
    20942170        // Catch exceptions during code compilation
    20952171        TryCatch exception;
    20962172
    20972173        // Execute code which was entered
    2098         bool rc = ExecuteCode(command, "console", true).IsEmpty();
    2099         if (exception.HasCaught())
    2100         {
    2101             HandleException(exception, "compile");
    2102             rc = true;
    2103         }
     2174        ExecuteCode(command, "console");
     2175        if (!HandleException(exception, "console"))
     2176            lout << endl;
    21042177
    21052178        // Stop all other threads
     
    21142187            usleep(1000);
    21152188
    2116         // In case of an exception add an empty line to the output
    2117         if (rc)
    2118             lout << endl;
    2119 
    21202189        // command has been executed, collect new command
    21212190        command = "";
     
    21252194
    21262195    Readline::StaticPopHistory("java.his");
    2127 
    2128     return true;
    21292196}
    21302197
     
    22962363    global->Set(String::New("Subscription"), sub, ReadOnly);
    22972364
     2365#ifdef HAVE_SQL
    22982366    Handle<FunctionTemplate> db = FunctionTemplate::New(WrapDatabase);
    22992367    db->SetClassName(String::New("Database"));
    23002368    db->InstanceTemplate()->SetInternalFieldCount(1);
    23012369    global->Set(String::New("Database"), db, ReadOnly);
     2370#endif
    23022371
    23032372    Handle<FunctionTemplate> thread = FunctionTemplate::New(WrapThread);
     
    23192388    fTemplateEvent = evt;
    23202389    fTemplateDescription = desc;
     2390
     2391#ifdef HAVE_MAIL
     2392    Handle<FunctionTemplate> mail = FunctionTemplate::New(ConstructorMail);
     2393    mail->SetClassName(String::New("Mail"));
     2394    global->Set(String::New("Mail"), mail, ReadOnly);
     2395#endif
    23212396
    23222397#ifdef HAVE_NOVA
     
    23722447    AddFormatToGlobal();
    23732448
    2374     bool rc = true;
    23752449    if (!exception.HasCaught())
    23762450    {
     
    23792453        Locker::StartPreemption(10);
    23802454
    2381         rc &= filename.empty() ? ExecuteConsole() : ExecuteFile(filename, true);
     2455        if (filename.empty())
     2456            ExecuteConsole();
     2457        else
     2458        {
     2459            // We call script->Run because it is the only way to
     2460            // catch exceptions.
     2461            const Handle<String> source = String::New(("include('"+filename+"');").c_str());
     2462            const Handle<String> origin = String::New("main");
     2463            const Handle<Script> script = Script::Compile(source, origin);
     2464            if (!script.IsEmpty())
     2465            {
     2466                JsSetState(3);
     2467                script->Run();
     2468            }
     2469        }
    23822470
    23832471        Locker::StopPreemption();
     
    23902478
    23912479    // Handle an exception
    2392     rc &= HandleException(exception, "main");
     2480    /*const bool rc =*/ HandleException(exception, "main");
    23932481
    23942482    // IsProfilerPaused()
  • trunk/FACT++/src/InterpreterV8.h

    r15101 r15156  
    5858#ifdef HAVE_V8
    5959    bool HandleException(v8::TryCatch &try_catch, const char *where);
    60     bool ExecuteFile(const std::string &name, bool main=false);
    61     bool ExecuteConsole();
    62     v8::Handle<v8::Value> ExecuteCode(const std::string &code, const std::string &file="internal", bool main=false);
     60    void ExecuteConsole();
     61    v8::Handle<v8::Value> ExecuteCode(const std::string &code, const std::string &file="internal");
    6362    v8::Handle<v8::Value> ExecuteInternal(const std::string &code);
    6463
    6564    void Thread(int &id, v8::Persistent<v8::Function> func, uint32_t ms);
     65
     66    std::vector<std::string> ValueToArray(const v8::Handle<v8::Value> &val);
    6667
    6768    v8::Handle<v8::Value> FuncWait(const v8::Arguments& args);
     
    7576    v8::Handle<v8::Value> FuncOut(const v8::Arguments& args);
    7677    v8::Handle<v8::Value> FuncFile(const v8::Arguments& args);
     78    v8::Handle<v8::Value> FuncSendMail(const v8::Arguments& args);
    7779    v8::Handle<v8::Value> FuncInclude(const v8::Arguments& args);
    7880    v8::Handle<v8::Value> FuncExit(const v8::Arguments& args);
     
    9698    static v8::Handle<v8::Value> Constructor(const v8::Arguments &args);
    9799
     100    static v8::Handle<v8::Value> ConstructorMail(const v8::Arguments &args);
     101
    98102#ifdef HAVE_NOVA
    99103    static double GetDataMember(const v8::Arguments &args, const char *name);
     
    120124    static v8::Handle<v8::Value> WrapInclude(const v8::Arguments &args)  { if (This) return This->FuncInclude(args);  else return v8::Undefined(); }
    121125    static v8::Handle<v8::Value> WrapFile(const v8::Arguments &args)     { if (This) return This->FuncFile(args);     else return v8::Undefined(); }
     126    static v8::Handle<v8::Value> WrapSendMail(const v8::Arguments &args) { if (This) return This->FuncSendMail(args); else return v8::Undefined(); }
    122127    static v8::Handle<v8::Value> WrapLog(const v8::Arguments &args)      { if (This) return This->FuncLog(args);      else return v8::Undefined(); }
    123128    static v8::Handle<v8::Value> WrapAlarm(const v8::Arguments &args)    { if (This) return This->FuncAlarm(args);    else return v8::Undefined(); }
Note: See TracChangeset for help on using the changeset viewer.