Subversion Repositories HomeAutomation

Rev

Rev 1601 | Rev 1603 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
1601 runge 1
/*
2
 *
3
 *  Copyright (C) 2010  Mattias Runge
4
 *
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
7
 *  the Free Software Foundation; either version 2 of the License, or
8
 *  (at your option) any later version.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
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.,
17
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
 *
19
 */
20
 
21
#include "Manager.h"
22
 
23
#include <fstream>
24
 
25
#include <boost/lexical_cast.hpp>
26
#include <boost/bind.hpp>
27
 
28
namespace atom {
29
namespace vm {
30
 
31
Manager::Pointer Manager::instance_;
32
 
33
Manager::Manager() : LOG("vm::Manager")
34
{
35
}
36
 
37
Manager::~Manager()
38
{
39
    this->io_service_.stop();
40
 
41
    this->plugins_.clear();
42
    this->context_.Dispose();
43
 
44
    for (ImportFunctionList::iterator it = this->functions_.begin(); it != this->functions_.end(); it++)
45
    {
46
        it->second.Dispose();
47
    }
48
}
49
 
50
void Manager::Create()
51
{
52
    Manager::instance_ = Manager::Pointer(new Manager());
53
}
54
 
55
Manager::Pointer Manager::Instance()
56
{
57
    return Manager::instance_;
58
}
59
 
60
void Manager::Delete()
61
{
62
    Manager::instance_.reset();
63
}
64
 
65
void Manager::AddPlugin(Plugin::Pointer plugin)
66
{
67
    this->plugins_[plugin->GetName()] = plugin;
68
}
69
 
70
void Manager::Start(std::string script_path)
71
{
72
    this->script_path_ = script_path;
73
    this->io_service_.post(boost::bind(&Manager::StartHandler, this));
74
}
75
 
76
void Manager::Call(std::string name, ArgumentListPointer arguments)
77
{
78
    this->io_service_.post(boost::bind(&Manager::CallHandler, this, name, arguments));
79
}
80
 
81
bool Manager::LoadScript(std::string scriptname)
82
{
83
    this->io_service_.post(boost::bind(&Manager::LoadScriptHandler, this, scriptname));
84
}
85
 
86
void Manager::CallHandler(std::string name, ArgumentListPointer arguments)
87
{
88
    v8::Context::Scope context_scope(this->context_);
89
    v8::TryCatch try_catch;
90
 
91
    if (this->functions_.find(name) == this->functions_.end())
92
    {
93
        LOG.Error("No such function found, " + name);
94
        return;
95
    }
96
 
97
    Value result = this->functions_[name]->Call(this->context_->Global(), arguments->size(), arguments->data());
98
 
99
    if (result.IsEmpty())
100
    {
101
        LOG.Error(this->FormatException(try_catch));
102
    }
103
}
104
 
105
void Manager::StartHandler()
106
{
107
    v8::Handle<v8::ObjectTemplate> raw_template = v8::ObjectTemplate::New();
108
 
109
    for (PluginList::iterator it = this->plugins_.begin(); it != this->plugins_.end(); it++)
110
    {
111
        ExportFunctionList export_functions = it->second->GetExportFunctions();
112
 
113
        for (ExportFunctionList::iterator it = export_functions.begin(); it != export_functions.end(); it++)
114
        {
115
            raw_template->Set(v8::String::New(it->first.data()), v8::FunctionTemplate::New(it->second));
116
        }
117
    }
118
 
119
    this->context_ = v8::Context::New(NULL, raw_template);
120
 
121
    v8::Context::Scope context_scope(this->context_);
122
 
123
    for (PluginList::iterator it = this->plugins_.begin(); it != this->plugins_.end(); it++)
124
    {
125
        std::string scriptname = "plugin/" + it->first + ".js";
126
 
127
        if (this->LoadScriptHandler(scriptname))
128
        {
129
            FunctionNameList import_functions = it->second->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
    }
148
 
149
    this->object_template_ = v8::Persistent<v8::ObjectTemplate>::New(raw_template);
150
 
151
    LOG.Info("VM initialized.");
152
 
153
    for (PluginList::iterator it = this->plugins_.begin(); it != this->plugins_.end(); it++)
154
    {
155
        it->second->InitializeDone();
156
    }
157
}
158
 
159
bool Manager::LoadScriptHandler(std::string scriptname)
160
{
161
    std::string path = this->script_path_ + scriptname;
162
    std::ifstream file(path.data());
163
 
164
    if (!file.is_open())
165
    {
166
        file.close();
167
        LOG.Warning("Could not load " + scriptname + ".");
168
        return false;
169
    }
170
 
171
    std::string code = "";
172
    std::string line;
173
 
174
    while (!file.eof())
175
    {
176
        std::getline(file, line);
177
 
178
        if (file.eof())
179
        {
180
            break;
181
        }
182
 
183
        code += line + "\n";
184
    }
185
 
1602 runge 186
    code += "\n";
187
 
1601 runge 188
    file.close();
189
 
190
    v8::Context::Scope context_scope(this->context_);
191
 
192
    v8::TryCatch try_catch;
193
 
194
    v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(code.data(), code.length()),
195
                                                        v8::String::New(scriptname.data(), scriptname.length()));
196
 
197
    if (script.IsEmpty())
198
    {
199
        LOG.Error(this->FormatException(try_catch));
200
        false;
201
    }
202
    else
203
    {
204
        Value result = script->Run();
205
 
206
        if (result.IsEmpty())
207
        {
208
            LOG.Error(this->FormatException(try_catch));
209
            false;
210
        }
211
    }
212
 
213
    LOG.Info("Loaded " + scriptname + " successfully!");
214
    return true;
215
}
216
 
217
std::string Manager::FormatException(v8::TryCatch& try_catch)
218
{
219
    std::string result;
220
 
221
    v8::HandleScope handle_scope;
222
    v8::String::Utf8Value exception(try_catch.Exception());
223
    v8::Handle<v8::Message> message = try_catch.Message();
224
 
225
    if (message.IsEmpty())
226
    {
227
        result = *exception;
228
    }
229
    else
230
    {
231
        v8::String::Utf8Value filename(message->GetScriptResourceName());
232
 
233
        result = std::string(*filename) + ":" + boost::lexical_cast<std::string>(message->GetLineNumber()) + ": " + std::string(*exception);
234
 
235
        /*v8::String::Utf8Value sourceline(message->GetSourceLine());
236
        string strSourceline = *sourceline;
237
 
238
        result += strSourceline + "\n";
239
 
240
        string underline = rpad("", message->GetStartColumn(), ' ');
241
        underline = rpad(underline, message->GetEndColumn(), '^');
242
 
243
        result += underline + "\n";*/
244
    }
245
 
246
    return result;
247
}
248
 
249
}; // namespace vm
250
}; // namespace atom