webmcp

annotate framework/bin/mcp.lua @ 233:827c44692141

Allow setting certain global variables in autoloader
author jbe
date Sat Feb 28 23:28:41 2015 +0100 (2015-02-28)
parents 82cc171e8510
children 36346c33a020
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@233 165 if self == _ENV then
jbe@233 166 _G[key] = false -- allow writing global variable
jbe@233 167 end
jbe@219 168 if merge and try_exec(merge_path .. ".lua") then
jbe@219 169 elseif merge and try_dir(merge_path .. "/") then
jbe@219 170 elseif try_exec(path .. ".lua") then
jbe@219 171 elseif try_dir(path .. "/") then
jbe/bsw@0 172 else end
jbe@233 173 local value = rawget(self, key)
jbe@233 174 if self == _ENV and value == false then
jbe@233 175 _G[key] = nil
jbe@233 176 return nil
jbe@233 177 else
jbe@233 178 return value
jbe@233 179 end
jbe/bsw@0 180 end
jbe@219 181 install_autoloader(_G, nil, "")
jbe@203 182 try_exec(WEBMCP_FRAMEWORK_PATH .. "env/__init.lua")
jbe@203 183 try_exec(WEBMCP_BASE_PATH .. "env/__init.lua")
jbe/bsw@0 184 end
jbe/bsw@0 185
jbe@214 186 -- replace Moonbridge listen function
jbe@214 187 local moonbridge_listen = listen
jbe@225 188 local listeners = {}
jbe@214 189 function listen(args)
jbe@214 190 listeners[#listeners+1] = args
jbe@214 191 end
jbe@214 192
jbe@203 193 -- prohibit (unintended) definition of new global variables
jbe@231 194 function global_metatable.__newindex()
jbe@231 195 error("Setting of global variable prohibited")
jbe@231 196 end
jbe@203 197
jbe@220 198 -- execute configurations and pre-fork initializers
jbe@206 199 for i, config_name in ipairs(WEBMCP_CONFIG_NAMES) do
jbe@206 200 execute.config(config_name)
jbe@206 201 end
jbe@220 202 execute.prefork_initializers()
jbe@206 203
jbe/bsw@0 204 -- interactive console mode
jbe@203 205 if WEBMCP_MODE == "interactive" then
jbe@229 206 _G.multirand = require "multirand" -- TODO: cleaner solution
jbe@215 207 execute.postfork_initializers()
jbe@203 208 trace.disable() -- avoids memory leakage (TODO: needs general solution for moonbridge?)
jbe/bsw@0 209 end
jbe/bsw@0 210
jbe@204 211 -- invoke moonbridge
jbe@206 212 if WEBMCP_MODE == "listen" then
jbe@207 213 local http = require("moonbridge_http")
jbe@211 214 for i, listener in ipairs(listeners) do
jbe@229 215 --listener.prepare = execute.postfork_initializers
jbe@229 216 listener.prepare = function()
jbe@229 217 _G.multirand = require "multirand"
jbe@229 218 execute.postfork_initializers()
jbe@229 219 end
jbe@211 220 listener.connect = http.generate_handler(
jbe@215 221 request.handler,
jbe@215 222 request.get_http_options()
jbe@211 223 )
jbe@211 224 listener.finish = execute.finalizers
jbe@211 225 moonbridge_listen(listener)
jbe@204 226 end
jbe@204 227 end
jbe@204 228

Impressum / About Us