Subversion Repositories HomeAutomation

Rev

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

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