27 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
28 #define REG_SCOPE_LOCK \
29 std::lock_guard<std::recursive_mutex> _guard(m_mutex);
32 std::mutex registrySingletonMutex;
34 #define SINGLETON_LOCK \
35 std::lock_guard<std::mutex> _guard(::registrySingletonMutex);
37 #define REG_SCOPE_LOCK
38 #define SINGLETON_LOCK
45 static inline std::string &
ltrim(std::string &
s) {
47 std::find_if(s.begin(), s.end(),
48 std::not1(std::ptr_fun<int, int>(std::isspace))));
53 static inline std::string &
rtrim(std::string &
s) {
54 s.erase(std::find_if(s.rbegin(), s.rend(),
55 std::not1(std::ptr_fun<int, int>(std::isspace)))
61 static inline std::string &
trim(std::string &
s) {
69 inline void factoryInfoSetHelper(std::string&
dest,
const std::string value,
70 const std::string& desc,
71 const std::string&
id) {
74 }
else if (dest != value) {
76 o <<
"new factory loaded for '" <<
id <<
"' with different "
77 << desc <<
": " << dest <<
" != " << value;
84 void operator() (
const char c) {
93 name.push_back(
'_');
break;
95 name.push_back(
'r');
break;
97 name.push_back(
'p');
break;
100 name.push_back(c);
break;
105 std::string old_style_name(
const std::string& name) {
106 return std::for_each(name.begin(), name.end(), OldStyleCnv()).name;
110 namespace Gaudi {
namespace PluginService {
112 Exception::Exception(
const std::string&
msg): m_msg(msg) {}
113 Exception::~Exception() throw() {}
114 const char* Exception::what()
const throw() {
115 return m_msg.c_str();
120 return Registry::instance().get(
id, type);
129 Registry::Registry(): m_initialized(false) {}
133 if (m_initialized)
return;
134 m_initialized =
true;
136 const char* envVar =
"PATH";
137 const char sep =
';';
139 const char* envVar =
"LD_LIBRARY_PATH";
140 const char sep =
':';
142 char *search_path = ::getenv(envVar);
144 logger().
debug(std::string(
"searching factories in ") + envVar);
145 std::string
path(search_path);
146 std::string::size_type pos = 0;
147 std::string::size_type newpos = 0;
148 while (pos != std::string::npos) {
151 newpos = path.find(sep, pos);
152 if (newpos != std::string::npos) {
153 dirName = path.substr(pos, newpos - pos);
156 dirName = path.substr(pos);
159 logger().
debug(std::string(
" looking into ") + dirName);
161 DIR *dir = opendir(dirName.c_str());
163 struct dirent * entry;
164 while ((entry = readdir(dir))) {
165 std::string name(entry->d_name);
167 std::string::size_type extpos = name.find(
".components");
168 if ((extpos != std::string::npos) &&
169 ((extpos+11) == name.size())) {
170 std::string fullPath = (dirName +
'/' + name);
173 stat(fullPath.c_str(), &buf);
174 if (!S_ISREG(buf.st_mode))
continue;
178 std::ifstream
factories(fullPath.c_str());
180 int factoriesCount = 0;
187 if (line.empty() || line[0] ==
'#')
continue;
189 std::string::size_type pos = line.find(
':');
190 if (pos == std::string::npos) {
191 std::ostringstream o;
192 o <<
"failed to parse line " << fullPath
197 const std::string lib(line, 0, pos);
198 const std::string fact(line, pos+1);
199 m_factories.insert(std::make_pair(fact,
FactoryInfo(lib)));
200 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
202 std::string old_name = old_style_name(fact);
203 if (fact != old_name) {
206 m_factories.insert(std::make_pair(old_name, old_info));
212 std::ostringstream o;
213 o <<
" found " << factoriesCount <<
" factories";
226 const std::string&
type,
const std::string& rtype,
227 const std::string& className,
231 FactoryMap::iterator entry = facts.find(
id);
232 if (entry == facts.end())
235 entry = facts.insert(std::make_pair(
id,
237 type, rtype, className, props))).first;
240 if (!entry->second.ptr) {
241 entry->second.ptr = factory;
243 factoryInfoSetHelper(entry->second.type, type,
"type",
id);
244 factoryInfoSetHelper(entry->second.rtype, rtype,
"return type",
id);
245 factoryInfoSetHelper(entry->second.className, className,
"class",
id);
247 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
249 std::string old_name = old_style_name(
id);
251 add(old_name, factory, type, rtype, className, props)
252 .properties[
"ReflexName"] =
"true";
254 return entry->second;
260 FactoryMap::const_iterator f = facts.find(
id);
261 if (f != facts.end())
263 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
264 const Properties& props = f->second.properties;
265 if (props.find(
"ReflexName") != props.end())
266 logger().
warning(
"requesting factory via old name '" +
id +
"'"
267 "use '" + f->second.className +
"' instead");
269 if (!f->second.ptr) {
270 if (!dlopen(f->second.library.c_str(), RTLD_LAZY | RTLD_GLOBAL)) {
272 " for factory " +
id);
273 char *dlmsg = dlerror();
280 if (f->second.type == type) {
281 return f->second.ptr;
283 logger().
warning(
"found factory " +
id +
", but of wrong type: " +
284 f->second.type +
" instead of " + type);
294 FactoryMap::const_iterator f = facts.find(
id);
295 if (f != facts.end())
303 Registry::addProperty(
const std::string&
id,
304 const std::string& k,
305 const std::string& v) {
308 FactoryMap::iterator f = facts.find(
id);
309 if (f != facts.end())
311 f->second.properties[k] = v;
316 std::set<Registry::KeyType> Registry::loadedFactories()
const {
320 for (FactoryMap::const_iterator f = facts.begin();
321 f != facts.end(); ++f)
332 realname = abi::__cxa_demangle(
id.name(), 0, 0, &status);
333 if (realname == 0)
return id.name();
334 std::string result(realname);
339 void Logger::report(
Level lvl,
const std::string&
msg) {
340 static const char* levels[] = {
"DEBUG : ",
344 if (lvl >=
level()) {
345 std::cerr << levels[lvl] << msg << std::endl;
360 using namespace Details;
364 else if (debugLevel > 0)
365 l.setLevel(Logger::Info);
366 else l.setLevel(Logger::Warning);
370 using namespace Details;
373 case Logger::Info:
return 1;
break;