Subversion Repositories HomeAutomation

Rev

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

Rev 1657 Rev 1740
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, std::string user_script_path)
75
void Manager::Start(std::string script_path, std::string user_script_path)
76
{
76
{
77
    this->script_path_ = script_path;
77
    this->script_path_ = script_path;
78
    this->user_script_path_ = user_script_path;
78
    this->user_script_path_ = user_script_path;
79
    this->io_service_.post(boost::bind(&Manager::StartHandler, this));
79
    this->io_service_.post(boost::bind(&Manager::StartHandler, this));
80
}
80
}
81
 
81
 
82
void Manager::CallOutput(std::string output)
82
void Manager::CallOutput(std::string output)
83
{
83
{
84
    if (this->current_plugin_name_ != "")
84
    if (this->current_plugin_name_ != "")
85
    {
85
    {
86
        for (unsigned int n = 0; n < this->plugins_.size(); n++)
86
        for (unsigned int n = 0; n < this->plugins_.size(); n++)
87
        {
87
        {
88
            if (this->plugins_[n]->GetName() == this->current_plugin_name_)
88
            if (this->plugins_[n]->GetName() == this->current_plugin_name_)
89
            {
89
            {
90
                this->plugins_[n]->CallOutput(this->current_request_id_, output);
90
                this->plugins_[n]->CallOutput(this->current_request_id_, output);
91
                return;
91
                return;
92
            }
92
            }
93
        }
93
        }
94
    }
94
    }
95
    else
95
    else
96
    {
96
    {
97
        LOG.Info(output);
97
        LOG.Info(output);
98
    }
98
    }
99
}
99
}
100
 
100
 
101
Value Manager::Export_Log(const v8::Arguments& args)
101
Value Manager::Export_Log(const v8::Arguments& args)
102
{
102
{
-
 
103
    v8::Locker lock;
103
    v8::Context::Scope context_scope(Manager::Instance()->GetContext());
104
    v8::Context::Scope context_scope(Manager::Instance()->GetContext());
104
   
105
   
105
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
106
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
106
   
107
   
107
    if (args.Length() < 1)
108
    if (args.Length() < 1)
108
    {
109
    {
109
        Manager::instance_->LOG.Error(std::string(__FUNCTION__) + ": To few arguments to log.");
110
        Manager::instance_->LOG.Error(std::string(__FUNCTION__) + ": To few arguments to log.");
110
        return v8::Undefined();
111
        return v8::Undefined();
111
    }
112
    }
112
   
113
   
113
    v8::String::AsciiValue str(args[0]);
114
    v8::String::AsciiValue str(args[0]);
114
       
115
       
115
    Manager::instance_->CallOutput(*str);
116
    Manager::instance_->CallOutput(*str);
116
   
117
   
117
    return v8::Undefined();
118
    return v8::Undefined();
118
}
119
}
119
 
120
 
120
void Manager::Call(std::string plugin_name, unsigned int request_id, std::string name, ArgumentListPointer arguments)
121
void Manager::Call(std::string plugin_name, unsigned int request_id, std::string name, ArgumentListPointer arguments)
121
{
122
{
122
    this->io_service_.post(boost::bind(&Manager::CallHandler, this, plugin_name, request_id, name, arguments));
123
    this->io_service_.post(boost::bind(&Manager::CallHandler, this, plugin_name, request_id, name, arguments));
123
}
124
}
124
 
125
 
125
void Manager::Execute(std::string plugin_name, unsigned int request_id, std::string code)
126
void Manager::Execute(std::string plugin_name, unsigned int request_id, std::string code)
126
{
127
{
127
    this->io_service_.post(boost::bind(&Manager::ExecuteHandler, this, plugin_name, request_id, code));
128
    this->io_service_.post(boost::bind(&Manager::ExecuteHandler, this, plugin_name, request_id, code));
128
}
129
}
129
 
130
 
130
bool Manager::CallHandler(std::string plugin_name, unsigned int request_id, std::string name, ArgumentListPointer arguments)
131
bool Manager::CallHandler(std::string plugin_name, unsigned int request_id, std::string name, ArgumentListPointer arguments)
131
{
132
{
-
 
133
    v8::Locker lock;
132
    v8::Context::Scope context_scope(this->context_);
134
    v8::Context::Scope context_scope(this->context_);
133
    v8::TryCatch try_catch;
135
    v8::TryCatch try_catch;
134
   
136
   
135
    this->current_plugin_name_ = plugin_name;
137
    this->current_plugin_name_ = plugin_name;
136
    this->current_request_id_ = request_id;
138
    this->current_request_id_ = request_id;
137
   
139
   
138
    if (this->functions_.find(name) == this->functions_.end())
140
    if (this->functions_.find(name) == this->functions_.end())
139
    {
141
    {
140
        this->CallOutput("No such function found, " + name);
142
        this->CallOutput("No such function found, " + name);
141
       
143
       
142
        this->current_plugin_name_ = "";
144
        this->current_plugin_name_ = "";
143
        this->current_request_id_ = 0;
145
        this->current_request_id_ = 0;
144
        return false;
146
        return false;
145
    }
147
    }
146
 
148
 
147
    //LOG.Debug("Call: " + name);
149
    //LOG.Debug("Call: " + name);
148
 
150
 
149
    Value result = this->functions_[name]->Call(this->context_->Global(), arguments->size(), arguments->data());
151
    Value result = this->functions_[name]->Call(this->context_->Global(), arguments->size(), arguments->data());
150
   
152
   
151
    if (result.IsEmpty())
153
    if (result.IsEmpty())
152
    {
154
    {
153
        this->CallOutput(this->FormatException(try_catch));
155
        this->CallOutput(this->FormatException(try_catch));
154
       
156
       
155
        this->current_plugin_name_ = "";
157
        this->current_plugin_name_ = "";
156
        this->current_request_id_ = 0;
158
        this->current_request_id_ = 0;
157
        return false;
159
        return false;
158
    }
160
    }
159
   
161
   
160
    //v8::String::AsciiValue response(result->ToString());
162
    //v8::String::AsciiValue response(result->ToString());
161
    //this->CallOutput(plugin_name, request_id, std::string(*response));
163
    //this->CallOutput(plugin_name, request_id, std::string(*response));
162
   
164
   
163
    this->current_plugin_name_ = "";
165
    this->current_plugin_name_ = "";
164
    this->current_request_id_ = 0;
166
    this->current_request_id_ = 0;
165
    return true;
167
    return true;
166
}
168
}
167
 
169
 
168
void Manager::StartHandler()
170
void Manager::StartHandler()
169
{
171
{
170
    v8::Handle<v8::ObjectTemplate> raw_template = v8::ObjectTemplate::New();
172
    v8::Handle<v8::ObjectTemplate> raw_template = v8::ObjectTemplate::New();
171
   
173
   
172
    raw_template->Set(v8::String::New("Log"), v8::FunctionTemplate::New(Manager::Export_Log));
174
    raw_template->Set(v8::String::New("Log"), v8::FunctionTemplate::New(Manager::Export_Log));
173
   
175
   
174
    for (unsigned int c = 0; c < this->plugins_.size(); c++)
176
    for (unsigned int c = 0; c < this->plugins_.size(); c++)
175
    {
177
    {
176
        ExportFunctionList export_functions = this->plugins_[c]->GetExportFunctions();
178
        ExportFunctionList export_functions = this->plugins_[c]->GetExportFunctions();
177
       
179
       
178
        for (ExportFunctionList::iterator it = export_functions.begin(); it != export_functions.end(); it++)
180
        for (ExportFunctionList::iterator it = export_functions.begin(); it != export_functions.end(); it++)
179
        {
181
        {
180
            raw_template->Set(v8::String::New(it->first.data()), v8::FunctionTemplate::New(it->second));
182
            raw_template->Set(v8::String::New(it->first.data()), v8::FunctionTemplate::New(it->second));
181
        }
183
        }
182
    }
184
    }
183
   
185
   
184
    this->context_ = v8::Context::New(NULL, raw_template);
186
    this->context_ = v8::Context::New(NULL, raw_template);
185
   
187
   
-
 
188
    v8::Locker lock;
186
    v8::Context::Scope context_scope(this->context_);
189
    v8::Context::Scope context_scope(this->context_);
187
   
190
   
188
    for (unsigned int c = 0; c < this->plugins_.size(); c++)
191
    for (unsigned int c = 0; c < this->plugins_.size(); c++)
189
    {
192
    {
190
        this->LoadScript("plugin/" + this->plugins_[c]->GetName() + ".js");
193
        this->LoadScript("plugin/" + this->plugins_[c]->GetName() + ".js");
191
    }
194
    }
192
   
195
   
193
    this->object_template_ = v8::Persistent<v8::ObjectTemplate>::New(raw_template);
196
    this->object_template_ = v8::Persistent<v8::ObjectTemplate>::New(raw_template);
194
   
197
   
195
    for (unsigned int c = 0; c < this->plugins_.size(); c++)
198
    for (unsigned int c = 0; c < this->plugins_.size(); c++)
196
    {
199
    {
197
        this->plugins_[c]->InitializeDone();
200
        this->plugins_[c]->InitializeDone();
198
    }
201
    }
199
}
202
}
200
 
203
 
201
bool Manager::ImportFunction(std::string functionname)
204
bool Manager::ImportFunction(std::string functionname)
202
{
205
{
-
 
206
    v8::Locker lock;
203
    v8::Context::Scope context_scope(this->context_);
207
    v8::Context::Scope context_scope(this->context_);
204
   
208
   
205
    v8::TryCatch try_catch;
209
    v8::TryCatch try_catch;
206
   
210
   
207
    v8::Handle<v8::String> process_name = v8::String::New(functionname.data());
211
    v8::Handle<v8::String> process_name = v8::String::New(functionname.data());
208
    v8::Handle<v8::Value> process_val = this->context_->Global()->Get(process_name);
212
    v8::Handle<v8::Value> process_val = this->context_->Global()->Get(process_name);
209
   
213
   
210
    if (!process_val->IsFunction())
214
    if (!process_val->IsFunction())
211
    {
215
    {
212
        LOG.Error(functionname + " was not found to be a function!");
216
        LOG.Error(functionname + " was not found to be a function!");
213
        return false;
217
        return false;
214
    }
218
    }
215
   
219
   
216
    v8::Handle<v8::Function> process_fun = v8::Handle<v8::Function>::Cast(process_val);
220
    v8::Handle<v8::Function> process_fun = v8::Handle<v8::Function>::Cast(process_val);
217
   
221
   
218
    this->functions_[functionname] = v8::Persistent<v8::Function>::New(process_fun);
222
    this->functions_[functionname] = v8::Persistent<v8::Function>::New(process_fun);
219
   
223
   
220
    return true;
224
    return true;
221
}
225
}
222
 
226
 
223
bool Manager::LoadScript(std::string scriptname)
227
bool Manager::LoadScript(std::string scriptname)
224
{
228
{
225
    for (unsigned int n = 0; n < this->loaded_scripts_.size(); n++)
229
    for (unsigned int n = 0; n < this->loaded_scripts_.size(); n++)
226
    {
230
    {
227
        if (this->loaded_scripts_[n] == scriptname)
231
        if (this->loaded_scripts_[n] == scriptname)
228
        {
232
        {
229
            LOG.Debug(scriptname + " is already loaded.");
233
            LOG.Debug(scriptname + " is already loaded.");
230
            return true;
234
            return true;
231
        }
235
        }
232
    }
236
    }
233
   
237
   
234
    std::string path = this->user_script_path_ + scriptname;
238
    std::string path = this->user_script_path_ + scriptname;
235
    std::ifstream file(path.data());
239
    std::ifstream file(path.data());
236
   
240
   
237
    if (!file.is_open())
241
    if (!file.is_open())
238
    {
242
    {
239
        path = this->script_path_ + scriptname;
243
        path = this->script_path_ + scriptname;
240
        file.open(path.data());
244
        file.open(path.data());
241
       
245
       
242
        if (!file.is_open())
246
        if (!file.is_open())
243
        {
247
        {
244
            file.close();
248
            file.close();
245
            LOG.Warning("Could not load " + scriptname + ".");
249
            LOG.Warning("Could not load " + scriptname + ".");
246
            return false;
250
            return false;
247
        }
251
        }
248
    }
252
    }
249
   
253
   
250
    std::string code = "";
254
    std::string code = "";
251
    std::string line;
255
    std::string line;
252
   
256
   
253
    while (!file.eof())
257
    while (!file.eof())
254
    {
258
    {
255
        std::getline(file, line);
259
        std::getline(file, line);
256
       
260
       
257
        if (file.eof())
261
        if (file.eof())
258
        {
262
        {
259
            break;
263
            break;
260
        }
264
        }
261
       
265
       
262
        code += line + "\n";
266
        code += line + "\n";
263
    }
267
    }
264
   
268
   
265
    code += "\n";
269
    code += "\n";
266
   
270
   
267
    file.close();
271
    file.close();
268
   
272
   
-
 
273
    v8::Locker lock;
269
    v8::Context::Scope context_scope(this->context_);
274
    v8::Context::Scope context_scope(this->context_);
270
   
275
   
271
    v8::TryCatch try_catch;
276
    v8::TryCatch try_catch;
272
   
277
   
273
    v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(code.data(), code.length()),
278
    v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(code.data(), code.length()),
274
                                                        v8::String::New(scriptname.data(), scriptname.length()));
279
                                                        v8::String::New(scriptname.data(), scriptname.length()));
275
   
280
   
276
    if (script.IsEmpty())
281
    if (script.IsEmpty())
277
    {
282
    {
278
        LOG.Error(this->FormatException(try_catch));
283
        LOG.Error(this->FormatException(try_catch));
279
        return false;
284
        return false;
280
    }
285
    }
281
    else
286
    else
282
    {
287
    {
283
        Value result = script->Run();
288
        Value result = script->Run();
284
       
289
       
285
        if (result.IsEmpty())
290
        if (result.IsEmpty())
286
        {
291
        {
287
            LOG.Error(this->FormatException(try_catch));
292
            LOG.Error(this->FormatException(try_catch));
288
            return false;
293
            return false;
289
        }
294
        }
290
    }
295
    }
291
   
296
   
292
    this->loaded_scripts_.push_back(scriptname);
297
    this->loaded_scripts_.push_back(scriptname);
293
   
298
   
294
    LOG.Info("\033[32mLoaded " + scriptname + " successfully.\033[0m");
299
    LOG.Info("\033[32mLoaded " + scriptname + " successfully.\033[0m");
295
    return true;
300
    return true;
296
}
301
}
297
 
302
 
298
void Manager::ExecuteHandler(std::string plugin_name, unsigned int request_id, std::string code)
303
void Manager::ExecuteHandler(std::string plugin_name, unsigned int request_id, std::string code)
299
{
304
{
300
    std::string scriptname = "execute_" + plugin_name + ".js";
305
    std::string scriptname = "execute_" + plugin_name + ".js";
301
   
306
   
-
 
307
    v8::Locker lock;
302
    v8::Context::Scope context_scope(this->context_);
308
    v8::Context::Scope context_scope(this->context_);
303
   
309
   
304
    v8::TryCatch try_catch;
310
    v8::TryCatch try_catch;
305
   
311
   
306
    v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(code.data(), code.length()),
312
    v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(code.data(), code.length()),
307
                                                        v8::String::New(scriptname.data(), scriptname.length()));
313
                                                        v8::String::New(scriptname.data(), scriptname.length()));
308
   
314
   
309
    this->current_plugin_name_ = plugin_name;
315
    this->current_plugin_name_ = plugin_name;
310
    this->current_request_id_ = request_id;
316
    this->current_request_id_ = request_id;
311
   
317
   
312
    if (script.IsEmpty())
318
    if (script.IsEmpty())
313
    {
319
    {
314
        this->CallOutput(this->FormatException(try_catch));
320
        this->CallOutput(this->FormatException(try_catch));
315
    }
321
    }
316
    else
322
    else
317
    {
323
    {
318
        Value result = script->Run();
324
        Value result = script->Run();
319
       
325
       
320
        if (result.IsEmpty())
326
        if (result.IsEmpty())
321
        {
327
        {
322
            this->CallOutput(this->FormatException(try_catch));
328
            this->CallOutput(this->FormatException(try_catch));
323
        }
329
        }
324
        else
330
        else
325
        {
331
        {
326
            //v8::String::AsciiValue response(result->ToString());
332
            //v8::String::AsciiValue response(result->ToString());
327
            //this->CallOutput(std::string(*response));
333
            //this->CallOutput(std::string(*response));
328
        }
334
        }
329
    }
335
    }
330
   
336
   
331
    this->current_plugin_name_ = "";
337
    this->current_plugin_name_ = "";
332
    this->current_request_id_ = 0;
338
    this->current_request_id_ = 0;
333
}
339
}
334
 
340
 
335
std::string Manager::FormatException(v8::TryCatch& try_catch)
341
std::string Manager::FormatException(v8::TryCatch& try_catch)
336
{
342
{
-
 
343
    v8::Locker lock;
337
    v8::Context::Scope context_scope(this->context_);
344
    v8::Context::Scope context_scope(this->context_);
338
   
345
   
339
    std::string result;
346
    std::string result;
340
   
347
   
341
    v8::HandleScope handle_scope;
348
    v8::HandleScope handle_scope;
342
    v8::String::Utf8Value exception(try_catch.Exception());
349
    v8::String::Utf8Value exception(try_catch.Exception());
343
    v8::Handle<v8::Message> message = try_catch.Message();
350
    v8::Handle<v8::Message> message = try_catch.Message();
344
   
351
   
345
    if (message.IsEmpty())
352
    if (message.IsEmpty())
346
    {
353
    {
347
        result = *exception;
354
        result = *exception;
348
    }
355
    }
349
    else
356
    else
350
    {
357
    {
351
        v8::String::Utf8Value filename(message->GetScriptResourceName());
358
        v8::String::Utf8Value filename(message->GetScriptResourceName());
352
       
359
       
353
        result = std::string(*filename) + ":" + boost::lexical_cast<std::string>(message->GetLineNumber()) + ": " + std::string(*exception);
360
        result = std::string(*filename) + ":" + boost::lexical_cast<std::string>(message->GetLineNumber()) + ": " + std::string(*exception);
354
       
361
       
355
        /*v8::String::Utf8Value sourceline(message->GetSourceLine());
362
        /*v8::String::Utf8Value sourceline(message->GetSourceLine());
356
        string strSourceline = *sourceline;
363
        string strSourceline = *sourceline;
357
       
364
       
358
        result += strSourceline + "\n";
365
        result += strSourceline + "\n";
359
       
366
       
360
        string underline = rpad("", message->GetStartColumn(), ' ');
367
        string underline = rpad("", message->GetStartColumn(), ' ');
361
        underline = rpad(underline, message->GetEndColumn(), '^');
368
        underline = rpad(underline, message->GetEndColumn(), '^');
362
       
369
       
363
        result += underline + "\n";*/
370
        result += underline + "\n";*/
364
    }
371
    }
365
   
372
   
366
    return result;
373
    return result;
367
}
374
}
368
   
375
   
369
}; // namespace vm
376
}; // namespace vm
370
}; // namespace atom
377
}; // namespace atom
371
 
378