See More

/////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2008-2016 Artyom Beilis (Tonkikh) // // See accompanying file COPYING.TXT file for licensing details. // /////////////////////////////////////////////////////////////////////////////// #define CPPCMS_SOURCE #include #include #include #include #include #include #include #include namespace cppcms { namespace plugin { namespace { struct init { init() { manager::instance(); scope::is_loaded(""); } } init_inst; } struct single_entry { single_entry(manager::entry_point_type ep=NULL,char const *sig="") : entry(ep),signature(sig) {} manager::entry_point_type entry; std::string signature; }; typedef std::map<:string> entries_type; typedef std::map<:string> plugins_type; struct manager::_data { plugins_type plugins; booster::mutex lock; }; manager &manager::instance() { static manager m; return m; } manager::manager() : d(new manager::_data()) { } manager::~manager() { } void manager::add_entry(char const *plugin,char const *name,manager::entry_point_type e,char const *sig) { try { booster::unique_lock<:mutex> guard(d->lock); d->plugins[plugin].insert(std::make_pair<:string>(name,single_entry(e,sig))); } catch(...){} } void manager::remove_entry(manager::entry_point_type e) { try { booster::unique_lock<:mutex> guard(d->lock); for(plugins_type::iterator p=d->plugins.begin();p!=d->plugins.end();++p) { for(entries_type::iterator it = p->second.begin();it!=p->second.end();++it) { if(it->second.entry==e) { p->second.erase(it); if(p->second.empty()) d->plugins.erase(p); return; } } } } catch(...){} } manager::entry_point_type manager::get_entry(std::string const &plugin,std::string const &name) { booster::unique_lock<:mutex> guard(d->lock); plugins_type::const_iterator p=d->plugins.find(plugin); if(p==d->plugins.end()) return 0; entries_type::const_iterator it=p->second.find(name); if(it!=p->second.end()) return it->second.entry; return 0; } std::string manager::signature(std::string const &plugin,std::string const &name) { booster::unique_lock<:mutex> guard(d->lock); plugins_type::const_iterator p=d->plugins.find(plugin); if(p==d->plugins.end()) return ""; entries_type::const_iterator it=p->second.find(name); if(it!=p->second.end()) return it->second.signature; return ""; } std::set<:string> manager::plugins() { std::set<:string> r; booster::unique_lock<:mutex> guard(d->lock); for(plugins_type::const_iterator p=d->plugins.begin();p!=d->plugins.end();++p) { r.insert(p->first); } return r; } bool manager::has_plugin(std::string const &plugin) { booster::unique_lock<:mutex> guard(d->lock); return d->plugins.find(plugin)!=d->plugins.end(); } std::set<:string> manager::entries(std::string const &name) { std::set<:string> r; booster::unique_lock<:mutex> guard(d->lock); plugins_type::const_iterator pit = d->plugins.find(name); if(pit==d->plugins.end()) return r; for(entries_type::const_iterator p=pit->second.begin();p!=pit->second.end();++p) { r.insert(p->first); } return r; } signature_error::signature_error(std::string const &msg) : msg_(msg) {} signature_error::~signature_error() throw() {} char const *signature_error::what() const throw() { return msg_.c_str(); } struct scope::_class_data { booster::mutex lock; std::set<:string> modules; }; scope::_class_data &scope::class_data() { static _class_data d; return d; } struct scope::_data { std::vector<:string> paths; std::string pattern; std::map<:string> > objects; }; scope::scope() : d(new scope::_data()) { } scope::scope(json::value const &v) : d(new scope::_data()) { init(v); } scope::~scope() { try { _class_data &cls = class_data(); booster::unique_lock<:mutex> guard(cls.lock); for(std::map<:string> >::iterator p=d->objects.begin();p!=d->objects.end();++p) { cls.modules.erase(p->first); } d->objects.clear(); } catch(...) {} } scope::scope(int argc,char **argv) : d(new scope::_data()) { json::value v = service::load_settings(argc,argv); init(v); } void scope::init(json::value const &v) { d->paths = v.get("plugin.paths",std::vector<:string>()); d->pattern = v.get("plugin.shared_object_pattern",std::string()); std::vector<:string> modules = v.get("plugin.modules",std::vector<:string>()); for(size_t i=0;i guard(cls.lock); return cls.modules.find(name)!=cls.modules.end(); } void scope::paths(std::vector<:string> const &paths) { d->paths = paths; } void scope::shared_object_pattern(std::string const &p) { d->pattern = p; } void scope::load(std::string const &name) { _class_data &cls = class_data(); booster::unique_lock<:mutex> guard(cls.lock); if(cls.modules.find(name)!=cls.modules.end()) return; std::string so_name; if(d->pattern.empty()) so_name = booster::shared_object::name(name); else so_name = (booster::locale::format(d->pattern) % name).str(std::locale::classic()); booster::shared_ptr<:shared_object> obj(new booster::shared_object()); int dlflags = booster::shared_object::load_lazy | booster::shared_object::load_global; if(d->paths.empty()) { if(!obj->open(so_name,dlflags)) throw cppcms_error("Failed to load " + so_name); } else { for(size_t i=0;ipaths.size();i++) { std::string path = d->paths[i]; if(path.empty()) path = so_name; else path = path + "/" + so_name; if(obj->open(path,dlflags)) break; } if(!obj->is_open()) { std::ostringstream ss; ss << "Failed to load " << so_name << " from "; for(size_t i=0;ipaths.size();i++) { if(i!=0) { ss << ", "; } ss << "`" << d->paths[i] << "'"; } throw cppcms_error(ss.str()); } } d->objects[name]=obj; cls.modules.insert(name); } bool scope::is_loaded_by_this_scope(std::string const &module) const { return d->objects.find(module)!=d->objects.end(); } booster::shared_object const &scope::get(std::string const &module) const { std::map<:string> >::const_iterator p = d->objects.find(module); if(p==d->objects.end()) throw cppcms_error("Module `" + module + "' wasn't loaded withing this scope"); return *p->second; } } // plugin } // cppcms