factory.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /******************************************************************************
  2. *
  3. * package: Log4Qt
  4. * file: factory.cpp
  5. * created: September 2007
  6. * author: Martin Heinrich
  7. *
  8. *
  9. * Copyright 2007 Martin Heinrich
  10. *
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. *
  23. ******************************************************************************/
  24. /******************************************************************************
  25. * Dependencies
  26. ******************************************************************************/
  27. #include "log4qt/helpers/factory.h"
  28. #include <QtCore/QDebug>
  29. #include <QtCore/QMetaObject>
  30. #include <QtCore/QMetaProperty>
  31. #include "log4qt/consoleappender.h"
  32. #include "log4qt/dailyrollingfileappender.h"
  33. #include "log4qt/fileappender.h"
  34. #include "log4qt/helpers/logerror.h"
  35. #include "log4qt/helpers/initialisationhelper.h"
  36. #include "log4qt/helpers/optionconverter.h"
  37. #include "log4qt/patternlayout.h"
  38. #include "log4qt/rollingfileappender.h"
  39. #include "log4qt/simplelayout.h"
  40. #include "log4qt/ttcclayout.h"
  41. #include "log4qt/varia/debugappender.h"
  42. #include "log4qt/varia/denyallfilter.h"
  43. #include "log4qt/varia/levelmatchfilter.h"
  44. #include "log4qt/varia/levelrangefilter.h"
  45. #include "log4qt/varia/listappender.h"
  46. #include "log4qt/varia/nullappender.h"
  47. #include "log4qt/varia/stringmatchfilter.h"
  48. namespace Log4Qt
  49. {
  50. /**************************************************************************
  51. * Declarations
  52. **************************************************************************/
  53. /**************************************************************************
  54. * C helper functions
  55. **************************************************************************/
  56. LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Factory)
  57. // Appenders
  58. Appender *console_file_appender()
  59. { return new ConsoleAppender; }
  60. Appender *create_daily_rolling_file_appender()
  61. { return new DailyRollingFileAppender; }
  62. Appender *create_debug_appender()
  63. { return new DebugAppender; }
  64. Appender *create_file_appender()
  65. { return new FileAppender; }
  66. Appender *create_list_appender()
  67. { return new ListAppender; }
  68. Appender *create_null_appender()
  69. { return new NullAppender; }
  70. Appender *create_rolling_file_appender()
  71. { return new RollingFileAppender; }
  72. // Filters
  73. Filter *create_deny_all_filter()
  74. { return new DenyAllFilter; }
  75. Filter *create_level_match_filter()
  76. { return new LevelMatchFilter; }
  77. Filter *create_level_range_filter()
  78. { return new LevelRangeFilter; }
  79. Filter *create_string_match_filter()
  80. { return new StringMatchFilter; }
  81. // Layouts
  82. Layout *create_pattern_layout()
  83. { return new PatternLayout; }
  84. Layout *create_simple_layout()
  85. { return new SimpleLayout; }
  86. Layout *create_ttcc_layout()
  87. { return new TTCCLayout; }
  88. /**************************************************************************
  89. * Class implementation: Factory
  90. **************************************************************************/
  91. Factory::Factory() :
  92. mObjectGuard(),
  93. mAppenderRegistry(),
  94. mFilterRegistry(),
  95. mLayoutRegistry()
  96. {
  97. registerDefaultAppenders();
  98. registerDefaultFilters();
  99. registerDefaultLayouts();
  100. }
  101. LOG4QT_IMPLEMENT_INSTANCE(Factory)
  102. Appender *Factory::doCreateAppender(const QString &rAppenderClassName)
  103. {
  104. QMutexLocker locker(&mObjectGuard);
  105. if (!mAppenderRegistry.contains(rAppenderClassName))
  106. {
  107. logger()->warn("Request for the creation of Appender with class '%1', which is not registered", rAppenderClassName);
  108. return 0;
  109. }
  110. return mAppenderRegistry.value(rAppenderClassName)();
  111. }
  112. Filter *Factory::doCreateFilter(const QString &rFilterClassName)
  113. {
  114. QMutexLocker locker(&mObjectGuard);
  115. if (!mFilterRegistry.contains(rFilterClassName))
  116. {
  117. logger()->warn("Request for the creation of Filter with class '%1', which is not registered", rFilterClassName);
  118. return 0;
  119. }
  120. return mFilterRegistry.value(rFilterClassName)();
  121. }
  122. Layout *Factory::doCreateLayout(const QString &rLayoutClassName)
  123. {
  124. QMutexLocker locker(&mObjectGuard);
  125. if (!mLayoutRegistry.contains(rLayoutClassName))
  126. {
  127. logger()->warn("Request for the creation of Layout with class '%1', which is not registered", rLayoutClassName);
  128. return 0;
  129. }
  130. return mLayoutRegistry.value(rLayoutClassName)();
  131. }
  132. void Factory::doRegisterAppender(const QString &rAppenderClassName,
  133. AppenderFactoryFunc pAppenderFactoryFunc)
  134. {
  135. QMutexLocker locker(&mObjectGuard);
  136. if(rAppenderClassName.isEmpty())
  137. {
  138. logger()->warn("Registering Appender factory function with empty class name");
  139. return;
  140. }
  141. mAppenderRegistry.insert(rAppenderClassName, pAppenderFactoryFunc);
  142. }
  143. void Factory::doRegisterFilter(const QString &rFilterClassName,
  144. FilterFactoryFunc pFilterFactoryFunc)
  145. {
  146. QMutexLocker locker(&mObjectGuard);
  147. if(rFilterClassName.isEmpty())
  148. {
  149. logger()->warn("Registering Filter factory function with empty class name");
  150. return;
  151. }
  152. mFilterRegistry.insert(rFilterClassName, pFilterFactoryFunc);
  153. }
  154. void Factory::doRegisterLayout(const QString &rLayoutClassName,
  155. LayoutFactoryFunc pLayoutFactoryFunc)
  156. {
  157. QMutexLocker locker(&mObjectGuard);
  158. if(rLayoutClassName.isEmpty())
  159. {
  160. logger()->warn("Registering Layout factory function with empty class name");
  161. return;
  162. }
  163. mLayoutRegistry.insert(rLayoutClassName, pLayoutFactoryFunc);
  164. }
  165. void Factory::doSetObjectProperty(QObject *pObject,
  166. const QString &rProperty,
  167. const QString &rValue)
  168. {
  169. // - Validate property
  170. // - Get correct property name from meta object
  171. // - Find specific property setter
  172. // - If no specfifc propery setter can be found,
  173. // find general property setter
  174. // - Call property setter
  175. QMetaProperty meta_property;
  176. if (!validateObjectProperty(meta_property, rProperty, pObject))
  177. return;
  178. QString property = QLatin1String(meta_property.name());
  179. QString type = QLatin1String(meta_property.typeName());
  180. logger()->debug("Setting property '%1' on object of class '%2' to value '%3'",
  181. property,
  182. QLatin1String(pObject->metaObject()->className()),
  183. rValue);
  184. QVariant value;
  185. bool ok = true;
  186. if (type == QLatin1String("bool"))
  187. value = OptionConverter::toBoolean(rValue, &ok);
  188. else if (type == QLatin1String("int"))
  189. value = OptionConverter::toInt(rValue, &ok);
  190. else if (type == QLatin1String("qint64") || type == QLatin1String("qlonglong"))
  191. value = OptionConverter::toQInt64(rValue, &ok);
  192. else if (type == QLatin1String("Log4Qt::Level"))
  193. value = QVariant::fromValue(OptionConverter::toLevel(rValue, &ok));
  194. else if (type == QLatin1String("QString"))
  195. value = rValue;
  196. else
  197. {
  198. LogError e = LOG4QT_ERROR(QT_TR_NOOP("Cannot convert to type '%1' for property '%2' on object of class '%3'"),
  199. CONFIGURATOR_UNKNOWN_TYPE_ERROR,
  200. "Log4Qt::Factory");
  201. e << type
  202. << property
  203. << QString::fromLatin1(pObject->metaObject()->className());
  204. logger()->error(e);
  205. return;
  206. }
  207. if (!ok)
  208. return;
  209. // Everything is checked and the type is the one of the property.
  210. // Write should never return false
  211. if (!meta_property.write(pObject, value))
  212. logger()->warn("Unxpected error result from QMetaProperty.write()");
  213. }
  214. void Factory::doUnregisterAppender(const QString &rAppenderClassName)
  215. {
  216. QMutexLocker locker(&mObjectGuard);
  217. if (!mAppenderRegistry.contains(rAppenderClassName))
  218. {
  219. logger()->warn("Request to unregister not registered Appender factory function for class '%1'", rAppenderClassName);
  220. return;
  221. }
  222. mAppenderRegistry.remove(rAppenderClassName);
  223. }
  224. void Factory::doUnregisterFilter(const QString &rFilterClassName)
  225. {
  226. QMutexLocker locker(&mObjectGuard);
  227. if (!mFilterRegistry.contains(rFilterClassName))
  228. {
  229. logger()->warn("Request to unregister not registered Filter factory function for class '%1'", rFilterClassName);
  230. return;
  231. }
  232. mFilterRegistry.remove(rFilterClassName);
  233. }
  234. void Factory::doUnregisterLayout(const QString &rLayoutClassName)
  235. {
  236. QMutexLocker locker(&mObjectGuard);
  237. if (!mLayoutRegistry.contains(rLayoutClassName))
  238. {
  239. logger()->warn("Request to unregister not registered Layout factory function for class '%1'", rLayoutClassName);
  240. return;
  241. }
  242. mLayoutRegistry.remove(rLayoutClassName);
  243. }
  244. void Factory::registerDefaultAppenders()
  245. {
  246. mAppenderRegistry.insert(QLatin1String("org.apache.log4j.ConsoleAppender"), console_file_appender);
  247. mAppenderRegistry.insert(QLatin1String("Log4Qt::ConsoleAppender"), console_file_appender);
  248. mAppenderRegistry.insert(QLatin1String("org.apache.log4j.DailyRollingFileAppender"), create_daily_rolling_file_appender);
  249. mAppenderRegistry.insert(QLatin1String("Log4Qt::DailyRollingFileAppender"), create_daily_rolling_file_appender);
  250. mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.DebugAppender"), create_debug_appender);
  251. mAppenderRegistry.insert(QLatin1String("Log4Qt::DebugAppender"), create_debug_appender);
  252. mAppenderRegistry.insert(QLatin1String("org.apache.log4j.FileAppender"), create_file_appender);
  253. mAppenderRegistry.insert(QLatin1String("Log4Qt::FileAppender"), create_file_appender);
  254. mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.ListAppender"), create_list_appender);
  255. mAppenderRegistry.insert(QLatin1String("Log4Qt::ListAppender"), create_list_appender);
  256. mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.NullAppender"), create_null_appender);
  257. mAppenderRegistry.insert(QLatin1String("Log4Qt::NullAppender"), create_null_appender);
  258. mAppenderRegistry.insert(QLatin1String("org.apache.log4j.RollingFileAppender"), create_rolling_file_appender);
  259. mAppenderRegistry.insert(QLatin1String("Log4Qt::RollingFileAppender"), create_rolling_file_appender);
  260. }
  261. void Factory::registerDefaultFilters()
  262. {
  263. mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.DenyAllFilter"), create_deny_all_filter);
  264. mFilterRegistry.insert(QLatin1String("Log4Qt::DenyAllFilter"), create_deny_all_filter);
  265. mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.LevelMatchFilter"), create_level_match_filter);
  266. mFilterRegistry.insert(QLatin1String("Log4Qt::LevelMatchFilter"), create_level_match_filter);
  267. mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.LevelRangeFilter"), create_level_range_filter);
  268. mFilterRegistry.insert(QLatin1String("Log4Qt::LevelRangeFilter"), create_level_range_filter);
  269. mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.StringMatchFilter"), create_string_match_filter);
  270. mFilterRegistry.insert(QLatin1String("Log4Qt::StringMatchFilter"), create_string_match_filter);
  271. }
  272. void Factory::registerDefaultLayouts()
  273. {
  274. mLayoutRegistry.insert(QLatin1String("org.apache.log4j.PatternLayout"), create_pattern_layout);
  275. mLayoutRegistry.insert(QLatin1String("Log4Qt::PatternLayout"), create_pattern_layout);
  276. mLayoutRegistry.insert(QLatin1String("org.apache.log4j.SimpleLayout"), create_simple_layout);
  277. mLayoutRegistry.insert(QLatin1String("Log4Qt::SimpleLayout"), create_simple_layout);
  278. mLayoutRegistry.insert(QLatin1String("org.apache.log4j.TTCCLayout"), create_ttcc_layout);
  279. mLayoutRegistry.insert(QLatin1String("Log4Qt::TTCCLayout"), create_ttcc_layout);
  280. }
  281. bool Factory::validateObjectProperty(QMetaProperty &rMetaProperty,
  282. const QString &rProperty,
  283. QObject *pObject)
  284. {
  285. // Validate:
  286. // - No null object pointer
  287. // - No empty property name
  288. // - Property exists on the object (QT or Java name)
  289. // - Property is readable
  290. // - Property is writable
  291. const char *p_context = "Log4Qt::Factory";
  292. LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to set property value on object"),
  293. CONFIGURATOR_PROPERTY_ERROR,
  294. p_context);
  295. if (!pObject)
  296. {
  297. LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Invalid null object pointer"),
  298. 0,
  299. p_context);
  300. e.addCausingError(ce);
  301. logger()->error(e);
  302. return false;
  303. }
  304. if (rProperty.isEmpty())
  305. {
  306. LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Invalid empty property name"),
  307. 0,
  308. p_context);
  309. e.addCausingError(ce);
  310. logger()->error(e);
  311. return false;
  312. }
  313. const QMetaObject *p_meta_object = pObject->metaObject();
  314. QString property = rProperty;
  315. int i = p_meta_object->indexOfProperty(property.toLatin1());
  316. if (i < 0)
  317. {
  318. // Try name with lower case first character. Java properties names
  319. // start upper case
  320. property[0] = property[0].toLower();
  321. i = p_meta_object->indexOfProperty(property.toLatin1());
  322. if (i < 0)
  323. {
  324. LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Property '%1' does not exist in class '%2'"),
  325. 0,
  326. p_context);
  327. ce << property
  328. << QString::fromLatin1(pObject->metaObject()->className());
  329. e.addCausingError(ce);
  330. logger()->error(e);
  331. return false;
  332. }
  333. }
  334. rMetaProperty = p_meta_object->property(i);
  335. if (!rMetaProperty.isWritable())
  336. {
  337. LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Property '%1' is not writable in class '%2'"),
  338. 0,
  339. p_context);
  340. ce << property
  341. << QString::fromLatin1(pObject->metaObject()->className());
  342. e.addCausingError(ce);
  343. logger()->error(e);
  344. return false;
  345. }
  346. return true;
  347. }
  348. /**************************************************************************
  349. * Implementation: Operators, Helper
  350. **************************************************************************/
  351. #ifndef QT_NO_DEBUG_STREAM
  352. QDebug operator<<(QDebug debug,
  353. const Factory &rFactory)
  354. {
  355. debug.nospace() << "Factory("
  356. << "appenderfactories:" << rFactory.registeredAppenders()
  357. << "filterfactories:" << rFactory.registeredFilters()
  358. << "layoutfactories:" << rFactory.registeredLayouts()
  359. << ")";
  360. return debug.space();
  361. }
  362. #endif // QT_NO_DEBUG_STREAM
  363. } // namespace Log4Qt