Subversion Repositories HomeAutomation

Rev

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

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