14 #include <Gaudi/PluginService.h>
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 <rim(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) {
62 return ltrim(rtrim(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);
126 realname = abi::__cxa_demangle(
id.c_str(), 0, 0, &status);
127 if (realname == 0)
return id;
128 std::string result(realname);
142 Registry::Registry(): m_initialized(false) {}
146 if (m_initialized)
return;
147 m_initialized =
true;
149 const char* envVar =
"PATH";
150 const char sep =
';';
152 const char* envVar =
"LD_LIBRARY_PATH";
153 const char sep =
':';
155 char *search_path = ::getenv(envVar);
157 logger().
debug(std::string(
"searching factories in ") + envVar);
158 std::string
path(search_path);
159 std::string::size_type pos = 0;
160 std::string::size_type newpos = 0;
161 while (pos != std::string::npos) {
164 newpos = path.find(sep, pos);
165 if (newpos != std::string::npos) {
166 dirName = path.substr(pos, newpos - pos);
169 dirName = path.substr(pos);
172 logger().
debug(std::string(
" looking into ") + dirName);
174 DIR *dir = opendir(dirName.c_str());
176 struct dirent * entry;
177 while ((entry = readdir(dir))) {
178 std::string name(entry->d_name);
180 std::string::size_type extpos = name.find(
".components");
181 if ((extpos != std::string::npos) &&
182 ((extpos+11) == name.size())) {
183 std::string fullPath = (dirName +
'/' + name);
186 stat(fullPath.c_str(), &buf);
187 if (!S_ISREG(buf.st_mode))
continue;
191 std::ifstream
factories(fullPath.c_str());
193 int factoriesCount = 0;
200 if (line.empty() || line[0] ==
'#')
continue;
202 std::string::size_type pos = line.find(
':');
203 if (pos == std::string::npos) {
204 std::ostringstream o;
205 o <<
"failed to parse line " << fullPath
210 const std::string lib(line, 0, pos);
211 const std::string fact(line, pos+1);
212 m_factories.insert(std::make_pair(fact,
FactoryInfo(lib)));
213 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
215 std::string old_name = old_style_name(fact);
216 if (fact != old_name) {
219 m_factories.insert(std::make_pair(old_name, old_info));
225 std::ostringstream o;
226 o <<
" found " << factoriesCount <<
" factories";
239 const std::string&
type,
const std::string& rtype,
240 const std::string& className,
244 FactoryMap::iterator entry = facts.find(
id);
245 if (entry == facts.end())
248 entry = facts.insert(std::make_pair(
id,
250 type, rtype, className, props))).first;
253 if (!entry->second.ptr) {
254 entry->second.ptr = factory;
256 factoryInfoSetHelper(entry->second.type, type,
"type",
id);
257 factoryInfoSetHelper(entry->second.rtype, rtype,
"return type",
id);
258 factoryInfoSetHelper(entry->second.className, className,
"class",
id);
260 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
262 std::string old_name = old_style_name(
id);
264 add(old_name, factory, type, rtype, className, props)
265 .properties[
"ReflexName"] =
"true";
267 return entry->second;
273 FactoryMap::const_iterator f = facts.find(
id);
274 if (f != facts.end())
276 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
277 const Properties& props = f->second.properties;
278 if (props.find(
"ReflexName") != props.end())
279 logger().
warning(
"requesting factory via old name '" +
id +
"'"
280 "use '" + f->second.className +
"' instead");
282 if (!f->second.ptr) {
283 if (!dlopen(f->second.library.c_str(), RTLD_LAZY | RTLD_GLOBAL)) {
285 " for factory " +
id);
286 char *dlmsg = dlerror();
293 if (f->second.type == type) {
294 return f->second.ptr;
296 logger().
warning(
"found factory " +
id +
", but of wrong type: " +
307 FactoryMap::const_iterator f = facts.find(
id);
308 if (f != facts.end())
316 Registry::addProperty(
const std::string&
id,
317 const std::string& k,
318 const std::string& v) {
321 FactoryMap::iterator f = facts.find(
id);
322 if (f != facts.end())
324 f->second.properties[k] = v;
329 std::set<Registry::KeyType> Registry::loadedFactories()
const {
333 for (FactoryMap::const_iterator f = facts.begin();
334 f != facts.end(); ++f)
342 void Logger::report(
Level lvl,
const std::string&
msg) {
343 static const char* levels[] = {
"DEBUG : ",
347 if (lvl >=
level()) {
348 std::cerr << levels[lvl] << msg << std::endl;
352 static std::auto_ptr<Logger> s_logger(
new Logger);
357 s_logger.reset(logger);
363 using namespace Details;
367 else if (debugLevel > 0)
368 l.setLevel(Logger::Info);
369 else l.setLevel(Logger::Warning);
373 using namespace Details;
376 case Logger::Info:
return 1;
break;