webmcp

view framework/bin/mcp.lua @ 239:1d2b463a65b0

Modified global_metatable.__newindex metamethod
author jbe
date Sun Mar 01 00:09:47 2015 +0100 (2015-03-01)
parents 4a735f198ded
children 8aa38ddcc1b2
line source
1 #!/usr/bin/env moonbridge
3 WEBMCP_VERSION = "2.0.0_devel"
5 -- allow control of global environment
6 local _G = _G
7 local allowed_globals = {}
8 local global_metatable = {
9 __index = _G,
10 __newindex = function(self, key, value)
11 _G[key] = value
12 end
13 }
14 _ENV = setmetatable({}, global_metatable)
16 -- check if interactive mode
17 if listen then -- defined by moonbridge
18 WEBMCP_MODE = "listen"
19 else
20 WEBMCP_MODE = "interactive"
21 end
23 -- configuration names are provided as 4th, 5th, etc. argument
24 WEBMCP_CONFIG_NAMES = {select(4, ...)}
26 -- determine framework and bath path from command line arguments
27 -- or print usage synopsis (if applicable)
28 do
29 local arg1, arg2, arg3 = ...
30 local helpout
31 if
32 arg1 == "-h" or arg1 == "--help" or
33 arg2 == "-h" or arg2 == "--help" -- if first arg is provided by wrapper
34 then
35 helpout = io.stdout
36 elseif
37 #WEBMCP_CONFIG_NAMES < 1 or
38 (WEBMCP_MODE == "interactive") ~= (arg3 == "INTERACTIVE")
39 then
40 helpout = io.stderr
41 end
42 if helpout then
43 helpout:write("Usage: moonbridge -- <framework path>/bin/mcp.lua <framework path> <app base path> <app name> <config name> [<config name> ...]\n")
44 helpout:write(" or: lua -i <framework path>/bin/mcp.lua <framework path> <app base path> INTERACTIVE <config name> [<config name> ...]\n")
45 if helpout == io.stderr then
46 return 1
47 else
48 return 0
49 end
50 end
51 local function append_trailing_slash(str)
52 return string.gsub(str, "([^/])$", function(last) return last .. "/" end)
53 end
54 WEBMCP_FRAMEWORK_PATH = append_trailing_slash(arg1)
55 WEBMCP_BASE_PATH = append_trailing_slash(arg2)
56 if WEBMCP_MODE == "listen" then
57 WEBMCP_APP_NAME = arg3
58 end
59 end
61 -- setup search paths for libraries
62 do
63 if string.match(package.path, "^[^;]") then
64 package.path = ";" .. package.path
65 end
66 package.path = WEBMCP_FRAMEWORK_PATH .. "lib/?.lua" .. package.path
67 -- find out which file name extension shared libraries have
68 local slib_exts = {}
69 for ext in string.gmatch(package.cpath, "%?%.([A-Za-z0-9_-]+)") do
70 if not slib_exts[ext] then
71 slib_exts[#slib_exts+1] = ext
72 slib_exts[ext] = true
73 end
74 end
75 local paths = {}
76 for i, ext in ipairs(slib_exts) do
77 paths[#paths+1] = WEBMCP_FRAMEWORK_PATH .. "accelerator/?." .. ext
78 end
79 for i, ext in ipairs(slib_exts) do
80 paths[#paths+1] = WEBMCP_FRAMEWORK_PATH .. "lib/?." .. ext
81 end
82 paths[#paths+1] = package.cpath
83 package.cpath = table.concat(paths, ";")
84 end
86 -- autoloader system for WebMCP environment "$WEBMCP_FRAMEWORK_PATH/env/",
87 -- application environment extensions "$WEBMCP_BASE_PATH/env/"
88 -- and models "$WEBMCP_BASE_PATH/model/"
89 do
90 local weakkey_mt = { __mode = "k" }
91 local autoloader_category = setmetatable({}, weakkey_mt)
92 local autoloader_path = setmetatable({}, weakkey_mt)
93 local autoloader_mt = {}
94 local function install_autoloader(self, category, path_fragment)
95 autoloader_category[self] = category
96 autoloader_path[self] = path_fragment
97 setmetatable(self, autoloader_mt)
98 end
99 local function try_exec(filename)
100 local file = io.open(filename, "r")
101 if file then
102 local filedata = file:read("*a")
103 io.close(file)
104 local func, errmsg = load(filedata, "=" .. filename, nil, _ENV)
105 if func then
106 func()
107 return true
108 else
109 error(errmsg, 0)
110 end
111 else
112 return false
113 end
114 end
115 function autoloader_mt.__index(self, key)
116 local category, base_path, merge_base_path, file_key
117 local merge = false
118 if
119 string.find(key, "^[a-z_][A-Za-z0-9_]*$") and
120 not string.find(key, "^__")
121 then
122 category = "env"
123 base_path = WEBMCP_FRAMEWORK_PATH .. "env/"
124 merge = true
125 merge_base_path = WEBMCP_BASE_PATH .. "env/"
126 file_key = key
127 elseif string.find(key, "^[A-Z][A-Za-z0-9]*$") then
128 category = "model"
129 base_path = WEBMCP_BASE_PATH .. "model/"
130 local first = true
131 file_key = string.gsub(key, "[A-Z]",
132 function(c)
133 if first then
134 first = false
135 return string.lower(c)
136 else
137 return "_" .. string.lower(c)
138 end
139 end
140 )
141 else
142 return
143 end
144 local required_category = autoloader_category[self]
145 if required_category and required_category ~= category then return end
146 local path_fragment = autoloader_path[self]
147 local path = base_path .. path_fragment .. file_key
148 local merge_path
149 if merge then
150 merge_path = merge_base_path .. path_fragment .. file_key
151 end
152 local function try_dir(dirname)
153 local dir = io.open(dirname)
154 if dir then
155 io.close(dir)
156 local obj = {}
157 install_autoloader(obj, category, path_fragment .. file_key .. "/")
158 rawset(self, key, obj)
159 try_exec(path .. "/__init.lua")
160 if merge then try_exec(merge_path .. "/__init.lua") end
161 return true
162 else
163 return false
164 end
165 end
166 if self == _G then
167 allowed_globals[key] = true
168 end
169 if merge and try_exec(merge_path .. ".lua") then
170 elseif merge and try_dir(merge_path .. "/") then
171 elseif try_exec(path .. ".lua") then
172 elseif try_dir(path .. "/") then
173 else end
174 if self == _G then
175 allowed_globals[key] = nil
176 end
177 return rawget(self, key)
178 end
179 install_autoloader(_G, nil, "")
180 try_exec(WEBMCP_FRAMEWORK_PATH .. "env/__init.lua")
181 try_exec(WEBMCP_BASE_PATH .. "env/__init.lua")
182 end
184 -- replace Moonbridge listen function
185 local moonbridge_listen = listen
186 local listeners = {}
187 function listen(args)
188 listeners[#listeners+1] = args
189 end
191 -- prohibit (unintended) definition of new global variables
192 function global_metatable.__newindex(self, key, value)
193 if not allowed_globals[key] then
194 error("Setting of global variable prohibited", 2)
195 end
196 _G[key] = value
197 end
199 -- execute configurations and pre-fork initializers
200 for i, config_name in ipairs(WEBMCP_CONFIG_NAMES) do
201 execute.config(config_name)
202 end
203 execute.prefork_initializers()
205 -- interactive console mode
206 if WEBMCP_MODE == "interactive" then
207 _G.multirand = require "multirand" -- TODO: cleaner solution
208 execute.postfork_initializers()
209 trace.disable() -- avoids memory leakage (TODO: needs general solution for moonbridge?)
210 end
212 -- invoke moonbridge
213 if WEBMCP_MODE == "listen" then
214 local http = require("moonbridge_http")
215 for i, listener in ipairs(listeners) do
216 --listener.prepare = execute.postfork_initializers
217 listener.prepare = function()
218 _G.multirand = require "multirand"
219 execute.postfork_initializers()
220 end
221 listener.connect = http.generate_handler(
222 request.handler,
223 request.get_http_options()
224 )
225 listener.finish = execute.finalizers
226 moonbridge_listen(listener)
227 end
228 end

Impressum / About Us