1 /* 2 * Hunt - A high-level D Programming Language Web framework that encourages rapid development and clean, pragmatic design. 3 * 4 * Copyright (C) 2015-2019, HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.framework.Simplify; 13 14 public import hunt.framework.config.ApplicationConfig; 15 public import hunt.framework.config.ConfigManager; 16 public import hunt.framework.Init; 17 public import hunt.framework.routing; 18 public import hunt.util.DateTime : time, date; 19 20 import hunt.framework.provider; 21 import hunt.logging; 22 import hunt.util.TaskPool; 23 import hunt.util.ResoureManager; 24 25 import poodinis; 26 27 import std.array; 28 import std.string; 29 import std.json; 30 31 ConfigManager configManager() { 32 return serviceContainer().resolve!(ConfigManager); 33 } 34 35 ApplicationConfig config() { 36 return serviceContainer().resolve!(ApplicationConfig); 37 } 38 39 RouteConfigManager routeConfig() { 40 return serviceContainer().resolve!(RouteConfigManager); 41 } 42 43 string url(string actionId) { 44 return url(actionId, null); 45 } 46 47 48 string url(string actionId, string[string] params, string group) { 49 // return routeConfig().createUrl(actionId, params, group); 50 51 // admin:user.user.view 52 string[] items = actionId.split(":"); 53 string m_group = ""; 54 string pathItem = ""; 55 if (items.length == 1) { 56 m_group = ""; 57 pathItem = actionId; 58 } else if (items.length == 2) { 59 m_group = items[0]; 60 pathItem = items[1]; 61 } else { 62 throw new Exception("Wrong format for actionId"); 63 } 64 65 if(m_group.empty) { 66 m_group = group; 67 } 68 69 return routeConfig().createUrl(pathItem, params, m_group); 70 } 71 72 string url(string actionId, string[string] params) { 73 // admin:user.user.view 74 // string[] items = actionId.split(":"); 75 // string group = ""; 76 // string pathItem = ""; 77 // if (items.length == 1) { 78 // group = ""; 79 // pathItem = actionId; 80 // } else if (items.length == 2) { 81 // group = items[0]; 82 // pathItem = items[1]; 83 // } else { 84 // throw new Exception("Wrong format for actionId"); 85 // } 86 87 // return routeConfig().createUrl(pathItem, params, group); 88 return url(actionId, params, null); 89 } 90 91 public import hunt.entity.EntityManager; 92 93 import hunt.entity.DefaultEntityManagerFactory; 94 import hunt.entity.EntityManagerFactory; 95 import hunt.framework.application.closer.EntityCloser; 96 import hunt.util.Common; 97 98 version(HUNT_TEST) { 99 import std.datetime; 100 import std.format; 101 import core.atomic; 102 import core.sync.mutex; 103 import core.thread ; 104 105 import hunt.framework.http.Request; 106 import hunt.util.ThreadHelper; 107 import hunt.collection.ArrayList; 108 import hunt.collection.ArrayList; 109 110 111 class EntityManagerInfo { 112 ThreadID threadId; 113 int number; 114 string path; 115 SysTime holdUpTime; 116 SysTime releaseTime; 117 // string connection; 118 119 this() { 120 threadId = getTid(); 121 holdUpTime = Clock.currTime; 122 releaseTime = holdUpTime; 123 number = atomicOp!"+="(counter, 1); 124 Request req = request(); 125 if(req is null) { 126 warning("Called from a non-Controller thread."); 127 } else { 128 path = req.path(); 129 } 130 } 131 132 override string toString() { 133 string str = format("%6d | %05d | %s | %s | %s | %s", 134 threadId, number, holdUpTime, releaseTime, releaseTime-holdUpTime, path); 135 136 return str; 137 } 138 139 shared static int counter; 140 __gshared EntityManagerInfo[] _entityManagers; 141 __gshared Mutex _mtx; 142 143 shared static this() { 144 // entityManagers = new ArrayList!EntityManagerInfo(500); 145 _mtx = new Mutex(); 146 } 147 148 static void append() { 149 EntityManagerInfo managerInfo = new EntityManagerInfo(); 150 _mtx.lock(); 151 scope(exit) _mtx.unlock(); 152 _entityManagers ~= managerInfo; 153 154 error(managerInfo.toString()); 155 } 156 157 static void remove() { 158 ThreadID tid = getTid(); 159 160 string reqPath; 161 Request req = request(); 162 if(req !is null) 163 reqPath = req.path(); 164 165 _mtx.lock(); 166 scope(exit) _mtx.unlock(); 167 168 bool isRemoved = false; 169 foreach(size_t index, EntityManagerInfo managerInfo; _entityManagers) { 170 if(managerInfo.threadId == tid && managerInfo.path == reqPath) { 171 managerInfo.releaseTime = Clock.currTime; 172 173 error(managerInfo); 174 if(index == 0) { 175 _entityManagers = _entityManagers[index+1 .. $]; 176 } else if(index + 1 == _entityManagers.length) { 177 _entityManagers = _entityManagers[0 .. index]; 178 } else { 179 _entityManagers = _entityManagers[0 .. index] ~ _entityManagers[index+1 .. $]; 180 } 181 isRemoved = true; 182 break; 183 } 184 185 if(!isRemoved) { 186 warningf("Nothing removed: ", tid, reqPath); 187 } 188 } 189 } 190 191 static string[] listAll() { 192 string[] result; 193 _mtx.lock(); 194 scope(exit) _mtx.unlock(); 195 196 foreach(EntityManagerInfo managerInfo; _entityManagers) { 197 result ~= managerInfo.toString(); 198 } 199 200 return result; 201 } 202 } 203 204 205 //global entity manager 206 private EntityManager _em; 207 EntityManager defaultEntityManager() { 208 if (_em is null) { 209 _em = serviceContainer.resolve!(EntityManagerFactory).currentEntityManager(); 210 registerResoure(new class Closeable { 211 void close() { 212 closeDefaultEntityManager(); 213 EntityManagerInfo.remove(); 214 } 215 }); 216 217 EntityManagerInfo.append(); 218 } 219 return _em; 220 } 221 222 } else { 223 //global entity manager 224 private EntityManager _em; 225 EntityManager defaultEntityManager() { 226 if (_em is null) { 227 _em = serviceContainer.resolve!(EntityManagerFactory).currentEntityManager(); 228 registerResoure(new class Closeable { 229 void close() { 230 closeDefaultEntityManager(); 231 } 232 }); 233 } 234 return _em; 235 } 236 } 237 238 //close global entity manager 239 void closeDefaultEntityManager() { 240 if (_em !is null) { 241 _em.close(); 242 _em = null; 243 } 244 } 245 246 // i18n 247 import hunt.framework.i18n.I18n; 248 249 private __gshared string _local /* = I18N_DEFAULT_LOCALE */ ; 250 251 @property string getLocale() { 252 if (_local) 253 return _local; 254 return serviceContainer.resolve!(I18n).defaultLocale; 255 } 256 257 @property setLocale(string _l) { 258 _local = toLower(_l); 259 } 260 261 string trans(A...)(string key, lazy A args) { 262 import std.format; 263 264 Appender!string buffer; 265 string text = _trans(key); 266 version (HUNT_DEBUG) 267 tracef("format string: %s, key: %s, args.length: ", text, key, args.length); 268 formattedWrite(buffer, text, args); 269 270 return buffer.data; 271 } 272 273 string transWithLocale(A...)(string locale, string key, lazy A args) { 274 import std.format; 275 276 Appender!string buffer; 277 string text = _transWithLocale(locale, key); 278 formattedWrite(buffer, text, args); 279 280 return buffer.data; 281 } 282 283 string transWithLocale(string locale, string key, JSONValue args) { 284 import hunt.framework.util.Formatter; 285 286 string text = _transWithLocale(locale, key); 287 return StrFormat(text, args); 288 } 289 290 ///key is [filename.key] 291 private string _trans(string key) { 292 string defaultValue = key; 293 I18n i18n = serviceContainer.resolve!(I18n); 294 if (!i18n.isResLoaded) { 295 logWarning("The lang resources haven't loaded yet!"); 296 return key; 297 } 298 299 auto p = getLocale in i18n.resources; 300 if (p !is null) { 301 return p.get(key, defaultValue); 302 } 303 logWarning("unsupported local: ", getLocale, ", use default now: ", i18n.defaultLocale); 304 305 p = i18n.defaultLocale in i18n.resources; 306 307 if (p !is null) { 308 return p.get(key, defaultValue); 309 } 310 311 logWarning("unsupported locale: ", i18n.defaultLocale); 312 313 return defaultValue; 314 } 315 316 ///key is [filename.key] 317 private string _transWithLocale(string locale, string key) { 318 string defaultValue = key; 319 I18n i18n = serviceContainer.resolve!(I18n); 320 if (!i18n.isResLoaded) { 321 logWarning("The lang resources has't loaded yet!"); 322 return key; 323 } 324 325 auto p = locale in i18n.resources; 326 if (p !is null) { 327 return p.get(key, defaultValue); 328 } 329 version(HUNT_DEBUG) { 330 logWarning("No language resource found for ", locale, 331 ". Use the default now: ", i18n.defaultLocale); 332 } 333 334 locale = i18n.defaultLocale; 335 p = locale in i18n.resources; 336 337 if (p !is null) { 338 return p.get(key, defaultValue); 339 } 340 341 warning("No language resource found for: ", locale); 342 343 return defaultValue; 344 } 345 346 347 import hunt.util.worker; 348 349 TaskQueue taskQueue() { 350 return serviceContainer.resolve!(TaskQueue); 351 }