Subversion Repositories HomeAutomation

Rev

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

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