webmcp

annotate framework/bin/mcp.lua @ 232:82cc171e8510

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

Impressum / About Us