Subversion Repositories HomeAutomation

Rev

Rev 1740 | Rev 2107 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
1601 runge 1
/*
2
 *
3
 *  Copyright (C) 2010  Mattias Runge
4
 *
5
 *  This program is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation; either version 2 of the License, or
8
 *  (at your option) any later version.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License along
16
 *  with this program; if not, write to the Free Software Foundation, Inc.,
17
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
 *
19
 */
20
 
21
#include "Manager.h"
22
 
23
#include <fstream>
24
 
25
#include <boost/lexical_cast.hpp>
26
#include <boost/bind.hpp>
27
 
28
namespace atom {
29
namespace vm {
30
 
31
Manager::Pointer Manager::instance_;
32
 
33
Manager::Manager() : LOG("vm::Manager")
34
{
35
}
36
 
37
Manager::~Manager()
38
{
39
    this->io_service_.stop();
40
 
41
    this->plugins_.clear();
42
    this->context_.Dispose();
43
 
44
    for (ImportFunctionList::iterator it = this->functions_.begin(); it != this->functions_.end(); it++)
45
    {
46
        it->second.Dispose();
47
    }
48
}
49
 
50
void Manager::Create()
51
{
52
    Manager::instance_ = Manager::Pointer(new Manager());
53
}
54
 
55
Manager::Pointer Manager::Instance()
56
{
57
    return Manager::instance_;
58
}
59
 
60
void Manager::Delete()
61
{
62
    Manager::instance_.reset();
63
}
64
 
1619 runge 65
v8::Persistent<v8::Context>& Manager::GetContext()
66
{
67
    return this->context_;
68
}
69
 
1601 runge 70
void Manager::AddPlugin(Plugin::Pointer plugin)
71
{
1603 runge 72
    this->plugins_.push_back(plugin);
1601 runge 73
}
74
 
1656 runge 75
void Manager::Start(std::string script_path, std::string user_script_path)
1601 runge 76
{
77
    this->script_path_ = script_path;
1656 runge 78
    this->user_script_path_ = user_script_path;
1601 runge 79
    this->io_service_.post(boost::bind(&Manager::StartHandler, this));
80
}
81
 
1647 runge 82
void Manager::CallOutput(std::string output)
1601 runge 83
{
1647 runge 84
    if (this->current_plugin_name_ != "")
1608 runge 85
    {
1647 runge 86
        for (unsigned int n = 0; n < this->plugins_.size(); n++)
1608 runge 87
        {
1647 runge 88
            if (this->plugins_[n]->GetName() == this->current_plugin_name_)
89
            {
90
                this->plugins_[n]->CallOutput(this->current_request_id_, output);
91
                return;
92
            }
1608 runge 93
        }
94
    }
1647 runge 95
    else
96
    {
97
        LOG.Info(output);
98
    }
1601 runge 99
}
100
 
1647 runge 101
Value Manager::Export_Log(const v8::Arguments& args)
102
{
1740 runge 103
    v8::Locker lock;
1647 runge 104
    v8::Context::Scope context_scope(Manager::Instance()->GetContext());
1741 runge 105
    v8::HandleScope handle_scope;
106
 
1647 runge 107
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
108
 
109
    if (args.Length() < 1)
110
    {
111
        Manager::instance_->LOG.Error(std::string(__FUNCTION__) + ": To few arguments to log.");
112
        return v8::Undefined();
113
    }
114
 
115
    v8::String::AsciiValue str(args[0]);
116
 
117
    Manager::instance_->CallOutput(*str);
118
 
1741 runge 119
    return handle_scope.Close(v8::Undefined());
1647 runge 120
}
121
 
1608 runge 122
void Manager::Call(std::string plugin_name, unsigned int request_id, std::string name, ArgumentListPointer arguments)
1601 runge 123
{
1608 runge 124
    this->io_service_.post(boost::bind(&Manager::CallHandler, this, plugin_name, request_id, name, arguments));
1601 runge 125
}
126
 
1608 runge 127
void Manager::Execute(std::string plugin_name, unsigned int request_id, std::string code)
1601 runge 128
{
1608 runge 129
    this->io_service_.post(boost::bind(&Manager::ExecuteHandler, this, plugin_name, request_id, code));
130
}
131
 
1647 runge 132
bool Manager::CallHandler(std::string plugin_name, unsigned int request_id, std::string name, ArgumentListPointer arguments)
1608 runge 133
{
1740 runge 134
    v8::Locker lock;
1601 runge 135
    v8::Context::Scope context_scope(this->context_);
136
    v8::TryCatch try_catch;
137
 
1647 runge 138
    this->current_plugin_name_ = plugin_name;
139
    this->current_request_id_ = request_id;
140
 
1601 runge 141
    if (this->functions_.find(name) == this->functions_.end())
142
    {
1647 runge 143
        this->CallOutput("No such function found, " + name);
144
 
145
        this->current_plugin_name_ = "";
146
        this->current_request_id_ = 0;
147
        return false;
1601 runge 148
    }
1604 runge 149
 
1642 runge 150
    //LOG.Debug("Call: " + name);
1625 runge 151
 
1601 runge 152
    Value result = this->functions_[name]->Call(this->context_->Global(), arguments->size(), arguments->data());
153
 
154
    if (result.IsEmpty())
155
    {
1647 runge 156
        this->CallOutput(this->FormatException(try_catch));
157
 
158
        this->current_plugin_name_ = "";
159
        this->current_request_id_ = 0;
160
        return false;
1601 runge 161
    }
1608 runge 162
 
1647 runge 163
    //v8::String::AsciiValue response(result->ToString());
164
    //this->CallOutput(plugin_name, request_id, std::string(*response));
1608 runge 165
 
1647 runge 166
    this->current_plugin_name_ = "";
167
    this->current_request_id_ = 0;
168
    return true;
1601 runge 169
}
170
 
171
void Manager::StartHandler()
172
{
1741 runge 173
    v8::Locker lock;
174
    v8::HandleScope handle_scope;
1601 runge 175
    v8::Handle<v8::ObjectTemplate> raw_template = v8::ObjectTemplate::New();
176
 
1647 runge 177
    raw_template->Set(v8::String::New("Log"), v8::FunctionTemplate::New(Manager::Export_Log));
178
 
1603 runge 179
    for (unsigned int c = 0; c < this->plugins_.size(); c++)
1601 runge 180
    {
1603 runge 181
        ExportFunctionList export_functions = this->plugins_[c]->GetExportFunctions();
1601 runge 182
 
183
        for (ExportFunctionList::iterator it = export_functions.begin(); it != export_functions.end(); it++)
184
        {
185
            raw_template->Set(v8::String::New(it->first.data()), v8::FunctionTemplate::New(it->second));
186
        }
187
    }
188
 
189
    this->context_ = v8::Context::New(NULL, raw_template);
190
 
1741 runge 191
 
1601 runge 192
    v8::Context::Scope context_scope(this->context_);
193
 
1603 runge 194
    for (unsigned int c = 0; c < this->plugins_.size(); c++)
1601 runge 195
    {
1608 runge 196
        this->LoadScript("plugin/" + this->plugins_[c]->GetName() + ".js");
1601 runge 197
    }
198
 
199
    this->object_template_ = v8::Persistent<v8::ObjectTemplate>::New(raw_template);
200
 
1603 runge 201
    for (unsigned int c = 0; c < this->plugins_.size(); c++)
1601 runge 202
    {
1603 runge 203
        this->plugins_[c]->InitializeDone();
1601 runge 204
    }
205
}
206
 
1608 runge 207
bool Manager::ImportFunction(std::string functionname)
1601 runge 208
{
1740 runge 209
    v8::Locker lock;
1608 runge 210
    v8::Context::Scope context_scope(this->context_);
211
 
212
    v8::TryCatch try_catch;
213
 
214
    v8::Handle<v8::String> process_name = v8::String::New(functionname.data());
215
    v8::Handle<v8::Value> process_val = this->context_->Global()->Get(process_name);
216
 
217
    if (!process_val->IsFunction())
218
    {
219
        LOG.Error(functionname + " was not found to be a function!");
220
        return false;
221
    }
222
 
223
    v8::Handle<v8::Function> process_fun = v8::Handle<v8::Function>::Cast(process_val);
224
 
225
    this->functions_[functionname] = v8::Persistent<v8::Function>::New(process_fun);
226
 
227
    return true;
228
}
229
 
230
bool Manager::LoadScript(std::string scriptname)
231
{
1644 runge 232
    for (unsigned int n = 0; n < this->loaded_scripts_.size(); n++)
233
    {
234
        if (this->loaded_scripts_[n] == scriptname)
235
        {
1657 runge 236
            LOG.Debug(scriptname + " is already loaded.");
1644 runge 237
            return true;
238
        }
239
    }
240
 
1656 runge 241
    std::string path = this->user_script_path_ + scriptname;
1601 runge 242
    std::ifstream file(path.data());
243
 
244
    if (!file.is_open())
245
    {
1656 runge 246
        path = this->script_path_ + scriptname;
247
        file.open(path.data());
248
 
249
        if (!file.is_open())
250
        {
251
            file.close();
252
            LOG.Warning("Could not load " + scriptname + ".");
253
            return false;
254
        }
1601 runge 255
    }
256
 
257
    std::string code = "";
258
    std::string line;
259
 
260
    while (!file.eof())
261
    {
262
        std::getline(file, line);
263
 
264
        if (file.eof())
265
        {
266
            break;
267
        }
268
 
269
        code += line + "\n";
270
    }
271
 
1602 runge 272
    code += "\n";
273
 
1601 runge 274
    file.close();
275
 
1740 runge 276
    v8::Locker lock;
1601 runge 277
    v8::Context::Scope context_scope(this->context_);
278
 
279
    v8::TryCatch try_catch;
280
 
281
    v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(code.data(), code.length()),
282
                                                        v8::String::New(scriptname.data(), scriptname.length()));
283
 
284
    if (script.IsEmpty())
285
    {
286
        LOG.Error(this->FormatException(try_catch));
1608 runge 287
        return false;
1601 runge 288
    }
289
    else
290
    {
291
        Value result = script->Run();
292
 
293
        if (result.IsEmpty())
294
        {
295
            LOG.Error(this->FormatException(try_catch));
1608 runge 296
            return false;
1601 runge 297
        }
298
    }
299
 
1644 runge 300
    this->loaded_scripts_.push_back(scriptname);
301
 
1657 runge 302
    LOG.Info("\033[32mLoaded " + scriptname + " successfully.\033[0m");
1601 runge 303
    return true;
304
}
305
 
1608 runge 306
void Manager::ExecuteHandler(std::string plugin_name, unsigned int request_id, std::string code)
307
{
308
    std::string scriptname = "execute_" + plugin_name + ".js";
309
 
1740 runge 310
    v8::Locker lock;
1608 runge 311
    v8::Context::Scope context_scope(this->context_);
312
 
313
    v8::TryCatch try_catch;
314
 
315
    v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(code.data(), code.length()),
316
                                                        v8::String::New(scriptname.data(), scriptname.length()));
317
 
1647 runge 318
    this->current_plugin_name_ = plugin_name;
319
    this->current_request_id_ = request_id;
320
 
1608 runge 321
    if (script.IsEmpty())
322
    {
1647 runge 323
        this->CallOutput(this->FormatException(try_catch));
1608 runge 324
    }
325
    else
326
    {
327
        Value result = script->Run();
328
 
329
        if (result.IsEmpty())
330
        {
1647 runge 331
            this->CallOutput(this->FormatException(try_catch));
1608 runge 332
        }
333
        else
334
        {
1647 runge 335
            //v8::String::AsciiValue response(result->ToString());
336
            //this->CallOutput(std::string(*response));
1608 runge 337
        }
338
    }
1647 runge 339
 
340
    this->current_plugin_name_ = "";
341
    this->current_request_id_ = 0;
1608 runge 342
}
343
 
1601 runge 344
std::string Manager::FormatException(v8::TryCatch& try_catch)
345
{
1740 runge 346
    v8::Locker lock;
1625 runge 347
    v8::Context::Scope context_scope(this->context_);
348
 
1601 runge 349
    std::string result;
350
 
351
    v8::HandleScope handle_scope;
352
    v8::String::Utf8Value exception(try_catch.Exception());
353
    v8::Handle<v8::Message> message = try_catch.Message();
354
 
355
    if (message.IsEmpty())
356
    {
357
        result = *exception;
358
    }
359
    else
360
    {
361
        v8::String::Utf8Value filename(message->GetScriptResourceName());
362
 
363
        result = std::string(*filename) + ":" + boost::lexical_cast<std::string>(message->GetLineNumber()) + ": " + std::string(*exception);
364
 
365
        /*v8::String::Utf8Value sourceline(message->GetSourceLine());
366
        string strSourceline = *sourceline;
367
 
368
        result += strSourceline + "\n";
369
 
370
        string underline = rpad("", message->GetStartColumn(), ' ');
371
        underline = rpad(underline, message->GetEndColumn(), '^');
372
 
373
        result += underline + "\n";*/
374
    }
375
 
376
    return result;
377
}
378
 
379
}; // namespace vm
380
}; // namespace atom