Subversion Repositories HomeAutomation

Rev

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

Rev 1601 Rev 1602
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_[plugin->GetName()] = plugin;
67
    this->plugins_[plugin->GetName()] = 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::Call(std::string name, ArgumentListPointer arguments)
77
{
77
{
78
    this->io_service_.post(boost::bind(&Manager::CallHandler, this, name, arguments));
78
    this->io_service_.post(boost::bind(&Manager::CallHandler, this, name, arguments));
79
}
79
}
80
 
80
 
81
bool Manager::LoadScript(std::string scriptname)
81
bool Manager::LoadScript(std::string scriptname)
82
{
82
{
83
    this->io_service_.post(boost::bind(&Manager::LoadScriptHandler, this, scriptname));
83
    this->io_service_.post(boost::bind(&Manager::LoadScriptHandler, this, scriptname));
84
}
84
}
85
 
85
 
86
void Manager::CallHandler(std::string name, ArgumentListPointer arguments)
86
void Manager::CallHandler(std::string name, ArgumentListPointer arguments)
87
{
87
{
88
    v8::Context::Scope context_scope(this->context_);
88
    v8::Context::Scope context_scope(this->context_);
89
    v8::TryCatch try_catch;
89
    v8::TryCatch try_catch;
90
   
90
   
91
    if (this->functions_.find(name) == this->functions_.end())
91
    if (this->functions_.find(name) == this->functions_.end())
92
    {
92
    {
93
        LOG.Error("No such function found, " + name);
93
        LOG.Error("No such function found, " + name);
94
        return;
94
        return;
95
    }
95
    }
96
   
96
   
97
    Value result = this->functions_[name]->Call(this->context_->Global(), arguments->size(), arguments->data());
97
    Value result = this->functions_[name]->Call(this->context_->Global(), arguments->size(), arguments->data());
98
   
98
   
99
    if (result.IsEmpty())
99
    if (result.IsEmpty())
100
    {
100
    {
101
        LOG.Error(this->FormatException(try_catch));
101
        LOG.Error(this->FormatException(try_catch));
102
    }
102
    }
103
}
103
}
104
 
104
 
105
void Manager::StartHandler()
105
void Manager::StartHandler()
106
{
106
{
107
    v8::Handle<v8::ObjectTemplate> raw_template = v8::ObjectTemplate::New();
107
    v8::Handle<v8::ObjectTemplate> raw_template = v8::ObjectTemplate::New();
108
   
108
   
109
    for (PluginList::iterator it = this->plugins_.begin(); it != this->plugins_.end(); it++)
109
    for (PluginList::iterator it = this->plugins_.begin(); it != this->plugins_.end(); it++)
110
    {
110
    {
111
        ExportFunctionList export_functions = it->second->GetExportFunctions();
111
        ExportFunctionList export_functions = it->second->GetExportFunctions();
112
       
112
       
113
        for (ExportFunctionList::iterator it = export_functions.begin(); it != export_functions.end(); it++)
113
        for (ExportFunctionList::iterator it = export_functions.begin(); it != export_functions.end(); it++)
114
        {
114
        {
115
            raw_template->Set(v8::String::New(it->first.data()), v8::FunctionTemplate::New(it->second));
115
            raw_template->Set(v8::String::New(it->first.data()), v8::FunctionTemplate::New(it->second));
116
        }
116
        }
117
    }
117
    }
118
   
118
   
119
    this->context_ = v8::Context::New(NULL, raw_template);
119
    this->context_ = v8::Context::New(NULL, raw_template);
120
   
120
   
121
    v8::Context::Scope context_scope(this->context_);
121
    v8::Context::Scope context_scope(this->context_);
122
   
122
   
123
    for (PluginList::iterator it = this->plugins_.begin(); it != this->plugins_.end(); it++)
123
    for (PluginList::iterator it = this->plugins_.begin(); it != this->plugins_.end(); it++)
124
    {
124
    {
125
        std::string scriptname = "plugin/" + it->first + ".js";
125
        std::string scriptname = "plugin/" + it->first + ".js";
126
       
126
       
127
        if (this->LoadScriptHandler(scriptname))
127
        if (this->LoadScriptHandler(scriptname))
128
        {
128
        {
129
            FunctionNameList import_functions = it->second->GetImportFunctionNames();
129
            FunctionNameList import_functions = it->second->GetImportFunctionNames();
130
           
130
           
131
            for (unsigned int n = 0; n < import_functions.size(); n++)
131
            for (unsigned int n = 0; n < import_functions.size(); n++)
132
            {
132
            {
133
                v8::Handle<v8::String> process_name = v8::String::New(import_functions[n].data());
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);
134
                v8::Handle<v8::Value> process_val = this->context_->Global()->Get(process_name);
135
               
135
               
136
                if (!process_val->IsFunction())
136
                if (!process_val->IsFunction())
137
                {
137
                {
138
                    LOG.Error(import_functions[n] + " was not found to be a function!");
138
                    LOG.Error(import_functions[n] + " was not found to be a function!");
139
                    continue;
139
                    continue;
140
                }
140
                }
141
               
141
               
142
                v8::Handle<v8::Function> process_fun = v8::Handle<v8::Function>::Cast(process_val);
142
                v8::Handle<v8::Function> process_fun = v8::Handle<v8::Function>::Cast(process_val);
143
               
143
               
144
                this->functions_[import_functions[n]] = v8::Persistent<v8::Function>::New(process_fun);
144
                this->functions_[import_functions[n]] = v8::Persistent<v8::Function>::New(process_fun);
145
            }
145
            }
146
        }
146
        }
147
    }
147
    }
148
   
148
   
149
    this->object_template_ = v8::Persistent<v8::ObjectTemplate>::New(raw_template);
149
    this->object_template_ = v8::Persistent<v8::ObjectTemplate>::New(raw_template);
150
   
150
   
151
    LOG.Info("VM initialized.");
151
    LOG.Info("VM initialized.");
152
   
152
   
153
    for (PluginList::iterator it = this->plugins_.begin(); it != this->plugins_.end(); it++)
153
    for (PluginList::iterator it = this->plugins_.begin(); it != this->plugins_.end(); it++)
154
    {
154
    {
155
        it->second->InitializeDone();
155
        it->second->InitializeDone();
156
    }
156
    }
157
}
157
}
158
 
158
 
159
bool Manager::LoadScriptHandler(std::string scriptname)
159
bool Manager::LoadScriptHandler(std::string scriptname)
160
{
160
{
161
    std::string path = this->script_path_ + scriptname;
161
    std::string path = this->script_path_ + scriptname;
162
    std::ifstream file(path.data());
162
    std::ifstream file(path.data());
163
   
163
   
164
    if (!file.is_open())
164
    if (!file.is_open())
165
    {
165
    {
166
        file.close();
166
        file.close();
167
        LOG.Warning("Could not load " + scriptname + ".");
167
        LOG.Warning("Could not load " + scriptname + ".");
168
        return false;
168
        return false;
169
    }
169
    }
170
   
170
   
171
    std::string code = "";
171
    std::string code = "";
172
    std::string line;
172
    std::string line;
173
   
173
   
174
    while (!file.eof())
174
    while (!file.eof())
175
    {
175
    {
176
        std::getline(file, line);
176
        std::getline(file, line);
177
       
177
       
178
        if (file.eof())
178
        if (file.eof())
179
        {
179
        {
180
            break;
180
            break;
181
        }
181
        }
182
       
182
       
183
        code += line + "\n";
183
        code += line + "\n";
184
    }
184
    }
-
 
185
   
-
 
186
    code += "\n";
185
   
187
   
186
    file.close();
188
    file.close();
187
   
189
   
188
    v8::Context::Scope context_scope(this->context_);
190
    v8::Context::Scope context_scope(this->context_);
189
   
191
   
190
    v8::TryCatch try_catch;
192
    v8::TryCatch try_catch;
191
   
193
   
192
    v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(code.data(), code.length()),
194
    v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(code.data(), code.length()),
193
                                                        v8::String::New(scriptname.data(), scriptname.length()));
195
                                                        v8::String::New(scriptname.data(), scriptname.length()));
194
   
196
   
195
    if (script.IsEmpty())
197
    if (script.IsEmpty())
196
    {
198
    {
197
        LOG.Error(this->FormatException(try_catch));
199
        LOG.Error(this->FormatException(try_catch));
198
        false;
200
        false;
199
    }
201
    }
200
    else
202
    else
201
    {
203
    {
202
        Value result = script->Run();
204
        Value result = script->Run();
203
       
205
       
204
        if (result.IsEmpty())
206
        if (result.IsEmpty())
205
        {
207
        {
206
            LOG.Error(this->FormatException(try_catch));
208
            LOG.Error(this->FormatException(try_catch));
207
            false;
209
            false;
208
        }
210
        }
209
    }
211
    }
210
   
212
   
211
    LOG.Info("Loaded " + scriptname + " successfully!");
213
    LOG.Info("Loaded " + scriptname + " successfully!");
212
    return true;
214
    return true;
213
}
215
}
214
 
216
 
215
std::string Manager::FormatException(v8::TryCatch& try_catch)
217
std::string Manager::FormatException(v8::TryCatch& try_catch)
216
{
218
{
217
    std::string result;
219
    std::string result;
218
   
220
   
219
    v8::HandleScope handle_scope;
221
    v8::HandleScope handle_scope;
220
    v8::String::Utf8Value exception(try_catch.Exception());
222
    v8::String::Utf8Value exception(try_catch.Exception());
221
    v8::Handle<v8::Message> message = try_catch.Message();
223
    v8::Handle<v8::Message> message = try_catch.Message();
222
   
224
   
223
    if (message.IsEmpty())
225
    if (message.IsEmpty())
224
    {
226
    {
225
        result = *exception;
227
        result = *exception;
226
    }
228
    }
227
    else
229
    else
228
    {
230
    {
229
        v8::String::Utf8Value filename(message->GetScriptResourceName());
231
        v8::String::Utf8Value filename(message->GetScriptResourceName());
230
       
232
       
231
        result = std::string(*filename) + ":" + boost::lexical_cast<std::string>(message->GetLineNumber()) + ": " + std::string(*exception);
233
        result = std::string(*filename) + ":" + boost::lexical_cast<std::string>(message->GetLineNumber()) + ": " + std::string(*exception);
232
       
234
       
233
        /*v8::String::Utf8Value sourceline(message->GetSourceLine());
235
        /*v8::String::Utf8Value sourceline(message->GetSourceLine());
234
        string strSourceline = *sourceline;
236
        string strSourceline = *sourceline;
235
       
237
       
236
        result += strSourceline + "\n";
238
        result += strSourceline + "\n";
237
       
239
       
238
        string underline = rpad("", message->GetStartColumn(), ' ');
240
        string underline = rpad("", message->GetStartColumn(), ' ');
239
        underline = rpad(underline, message->GetEndColumn(), '^');
241
        underline = rpad(underline, message->GetEndColumn(), '^');
240
       
242
       
241
        result += underline + "\n";*/
243
        result += underline + "\n";*/
242
    }
244
    }
243
   
245
   
244
    return result;
246
    return result;
245
}
247
}
246
   
248
   
247
}; // namespace vm
249
}; // namespace vm
248
}; // namespace atom
250
}; // namespace atom
249
 
251