Subversion Repositories HomeAutomation

Rev

Rev 1608 | Rev 1625 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

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