Subversion Repositories HomeAutomation

Rev

Rev 1608 | Rev 1625 | 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
 
75
void Manager::Start(std::string script_path)
76
{
77
    this->script_path_ = script_path;
78
    this->io_service_.post(boost::bind(&Manager::StartHandler, this));
79
}
80
 
1608 runge 81
void Manager::SendResponse(std::string plugin_name, unsigned int request_id, std::string response)
1601 runge 82
{
1608 runge 83
    for (unsigned int n = 0; n < this->plugins_.size(); n++)
84
    {
85
        if (this->plugins_[n]->GetName() == plugin_name)
86
        {
87
            this->plugins_[n]->ExecutionResult(response, request_id);
88
            return;
89
        }
90
    }
1601 runge 91
}
92
 
1608 runge 93
void Manager::Call(std::string plugin_name, unsigned int request_id, std::string name, ArgumentListPointer arguments)
1601 runge 94
{
1608 runge 95
    this->io_service_.post(boost::bind(&Manager::CallHandler, this, plugin_name, request_id, name, arguments));
1601 runge 96
}
97
 
1608 runge 98
void Manager::Execute(std::string plugin_name, unsigned int request_id, std::string code)
1601 runge 99
{
1608 runge 100
    this->io_service_.post(boost::bind(&Manager::ExecuteHandler, this, plugin_name, request_id, code));
101
}
102
 
103
void Manager::CallHandler(std::string plugin_name, unsigned int request_id, std::string name, ArgumentListPointer arguments)
104
{
1601 runge 105
    v8::Context::Scope context_scope(this->context_);
106
    v8::TryCatch try_catch;
107
 
108
    if (this->functions_.find(name) == this->functions_.end())
109
    {
1608 runge 110
        this->SendResponse(plugin_name, request_id, "No such function found, " + name);
1601 runge 111
        return;
112
    }
1604 runge 113
 
1601 runge 114
    Value result = this->functions_[name]->Call(this->context_->Global(), arguments->size(), arguments->data());
115
 
116
    if (result.IsEmpty())
117
    {
1608 runge 118
        this->SendResponse(plugin_name, request_id, this->FormatException(try_catch));
119
        return;
1601 runge 120
    }
1608 runge 121
 
122
    v8::String::AsciiValue response(result->ToString());
123
 
124
    this->SendResponse(plugin_name, request_id, std::string(*response));
1601 runge 125
}
126
 
127
void Manager::StartHandler()
128
{
129
    v8::Handle<v8::ObjectTemplate> raw_template = v8::ObjectTemplate::New();
130
 
1603 runge 131
    for (unsigned int c = 0; c < this->plugins_.size(); c++)
1601 runge 132
    {
1603 runge 133
        ExportFunctionList export_functions = this->plugins_[c]->GetExportFunctions();
1601 runge 134
 
135
        for (ExportFunctionList::iterator it = export_functions.begin(); it != export_functions.end(); it++)
136
        {
137
            raw_template->Set(v8::String::New(it->first.data()), v8::FunctionTemplate::New(it->second));
138
        }
139
    }
140
 
141
    this->context_ = v8::Context::New(NULL, raw_template);
142
 
143
    v8::Context::Scope context_scope(this->context_);
144
 
1603 runge 145
    for (unsigned int c = 0; c < this->plugins_.size(); c++)
1601 runge 146
    {
1608 runge 147
        this->LoadScript("plugin/" + this->plugins_[c]->GetName() + ".js");
1601 runge 148
    }
149
 
150
    this->object_template_ = v8::Persistent<v8::ObjectTemplate>::New(raw_template);
151
 
1603 runge 152
    for (unsigned int c = 0; c < this->plugins_.size(); c++)
1601 runge 153
    {
1603 runge 154
        this->plugins_[c]->InitializeDone();
1601 runge 155
    }
1608 runge 156
 
157
    LOG.Info("VM initialized.");
1601 runge 158
}
159
 
1608 runge 160
bool Manager::ImportFunction(std::string functionname)
1601 runge 161
{
1608 runge 162
    v8::Context::Scope context_scope(this->context_);
163
 
164
    v8::TryCatch try_catch;
165
 
166
    v8::Handle<v8::String> process_name = v8::String::New(functionname.data());
167
    v8::Handle<v8::Value> process_val = this->context_->Global()->Get(process_name);
168
 
169
    if (!process_val->IsFunction())
170
    {
171
        LOG.Error(functionname + " was not found to be a function!");
172
        return false;
173
    }
174
 
175
    v8::Handle<v8::Function> process_fun = v8::Handle<v8::Function>::Cast(process_val);
176
 
177
    this->functions_[functionname] = v8::Persistent<v8::Function>::New(process_fun);
178
 
179
    return true;
180
}
181
 
182
bool Manager::LoadScript(std::string scriptname)
183
{
1601 runge 184
    std::string path = this->script_path_ + scriptname;
185
    std::ifstream file(path.data());
186
 
187
    if (!file.is_open())
188
    {
189
        file.close();
190
        LOG.Warning("Could not load " + scriptname + ".");
191
        return false;
192
    }
193
 
194
    std::string code = "";
195
    std::string line;
196
 
197
    while (!file.eof())
198
    {
199
        std::getline(file, line);
200
 
201
        if (file.eof())
202
        {
203
            break;
204
        }
205
 
206
        code += line + "\n";
207
    }
208
 
1602 runge 209
    code += "\n";
210
 
1601 runge 211
    file.close();
212
 
213
    v8::Context::Scope context_scope(this->context_);
214
 
215
    v8::TryCatch try_catch;
216
 
217
    v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(code.data(), code.length()),
218
                                                        v8::String::New(scriptname.data(), scriptname.length()));
219
 
220
    if (script.IsEmpty())
221
    {
222
        LOG.Error(this->FormatException(try_catch));
1608 runge 223
        return false;
1601 runge 224
    }
225
    else
226
    {
227
        Value result = script->Run();
228
 
229
        if (result.IsEmpty())
230
        {
231
            LOG.Error(this->FormatException(try_catch));
1608 runge 232
            return false;
1601 runge 233
        }
234
    }
235
 
1603 runge 236
    LOG.Info("Loaded " + scriptname + " successfully.");
1601 runge 237
    return true;
238
}
239
 
1608 runge 240
void Manager::ExecuteHandler(std::string plugin_name, unsigned int request_id, std::string code)
241
{
242
    std::string scriptname = "execute_" + plugin_name + ".js";
243
 
244
    v8::Context::Scope context_scope(this->context_);
245
 
246
    v8::TryCatch try_catch;
247
 
248
    v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(code.data(), code.length()),
249
                                                        v8::String::New(scriptname.data(), scriptname.length()));
250
 
251
    if (script.IsEmpty())
252
    {
253
        this->SendResponse(plugin_name, request_id, this->FormatException(try_catch));
254
    }
255
    else
256
    {
257
        Value result = script->Run();
258
 
259
        if (result.IsEmpty())
260
        {
261
            this->SendResponse(plugin_name, request_id, this->FormatException(try_catch));
262
        }
263
        else
264
        {
265
            v8::String::AsciiValue response(result->ToString());
266
 
267
            this->SendResponse(plugin_name, request_id, std::string(*response));
268
        }
269
    }
270
}
271
 
1601 runge 272
std::string Manager::FormatException(v8::TryCatch& try_catch)
273
{
274
    std::string result;
275
 
276
    v8::HandleScope handle_scope;
277
    v8::String::Utf8Value exception(try_catch.Exception());
278
    v8::Handle<v8::Message> message = try_catch.Message();
279
 
280
    if (message.IsEmpty())
281
    {
282
        result = *exception;
283
    }
284
    else
285
    {
286
        v8::String::Utf8Value filename(message->GetScriptResourceName());
287
 
288
        result = std::string(*filename) + ":" + boost::lexical_cast<std::string>(message->GetLineNumber()) + ": " + std::string(*exception);
289
 
290
        /*v8::String::Utf8Value sourceline(message->GetSourceLine());
291
        string strSourceline = *sourceline;
292
 
293
        result += strSourceline + "\n";
294
 
295
        string underline = rpad("", message->GetStartColumn(), ' ');
296
        underline = rpad(underline, message->GetEndColumn(), '^');
297
 
298
        result += underline + "\n";*/
299
    }
300
 
301
    return result;
302
}
303
 
304
}; // namespace vm
305
}; // namespace atom