fileappender.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /******************************************************************************
  2. *
  3. * package: Log4Qt
  4. * file: fileappender.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/fileappender.h"
  28. #include <QtCore/QDir>
  29. #include <QtCore/QFile>
  30. #include <QtCore/QFileInfo>
  31. #include <QtCore/QDebug>
  32. #include <QtCore/QTextStream>
  33. #include <QtCore/QTextCodec>
  34. #include "log4qt/layout.h"
  35. #include "log4qt/loggingevent.h"
  36. namespace Log4Qt
  37. {
  38. /**************************************************************************
  39. * Declarations
  40. **************************************************************************/
  41. /**************************************************************************
  42. * C helper functions
  43. **************************************************************************/
  44. /**************************************************************************
  45. * Class implementation: FileAppender
  46. **************************************************************************/
  47. FileAppender::FileAppender(QObject *pParent) :
  48. WriterAppender(pParent),
  49. mAppendFile(false),
  50. mBufferedIo(true),
  51. mFileName(),
  52. mpFile(0),
  53. mpTextStream(0)
  54. {
  55. }
  56. FileAppender::FileAppender(Layout *pLayout,
  57. const QString &rFileName,
  58. QObject *pParent) :
  59. WriterAppender(pLayout, pParent),
  60. mAppendFile(false),
  61. mBufferedIo(true),
  62. mFileName(rFileName),
  63. mpFile(0),
  64. mpTextStream(0)
  65. {
  66. }
  67. FileAppender::FileAppender(Layout *pLayout,
  68. const QString &rFileName,
  69. bool append,
  70. QObject *pParent) :
  71. WriterAppender(pLayout, pParent),
  72. mAppendFile(append),
  73. mBufferedIo(true),
  74. mFileName(rFileName),
  75. mpFile(0),
  76. mpTextStream(0)
  77. {
  78. }
  79. FileAppender::FileAppender(Layout *pLayout,
  80. const QString &rFileName,
  81. bool append,
  82. bool buffered,
  83. QObject *pParent) :
  84. WriterAppender(pLayout, pParent),
  85. mAppendFile(append),
  86. mBufferedIo(buffered),
  87. mFileName(rFileName),
  88. mpFile(0),
  89. mpTextStream(0)
  90. {
  91. }
  92. FileAppender::~FileAppender()
  93. {
  94. close();
  95. }
  96. void FileAppender::activateOptions()
  97. {
  98. QMutexLocker locker(&mObjectGuard);
  99. if (mFileName.isEmpty())
  100. {
  101. LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of Appender '%1' that requires file and has no file set"),
  102. APPENDER_ACTIVATE_MISSING_FILE_ERROR);
  103. e << name();
  104. logger()->error(e);
  105. return;
  106. }
  107. closeFile();
  108. openFile();
  109. WriterAppender::activateOptions();
  110. }
  111. void FileAppender::close()
  112. {
  113. QMutexLocker locker(&mObjectGuard);
  114. if (isClosed())
  115. return;
  116. WriterAppender::close();
  117. closeFile();
  118. }
  119. bool FileAppender::checkEntryConditions() const
  120. {
  121. // Q_ASSERT_X(, "FileAppender::checkEntryConditions()", "Lock must be held by caller")
  122. if (!mpFile || !mpTextStream)
  123. {
  124. LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without open file"),
  125. APPENDER_NO_OPEN_FILE_ERROR);
  126. e << name();
  127. logger()->error(e);
  128. return false;
  129. }
  130. return WriterAppender::checkEntryConditions();
  131. }
  132. void FileAppender::closeFile()
  133. {
  134. // Q_ASSERT_X(, "FileAppender::closeFile()", "Lock must be held by caller")
  135. if (mpFile)
  136. logger()->debug("Closing file '%1' for appender '%2'", mpFile->fileName(), name());
  137. setWriter(0);
  138. delete mpTextStream;
  139. mpTextStream = 0;
  140. delete mpFile;
  141. mpFile = 0;
  142. }
  143. #ifndef QT_NO_DEBUG_STREAM
  144. QDebug FileAppender::debug(QDebug &rDebug) const
  145. {
  146. QString layout_name;
  147. if (layout())
  148. layout_name = layout()->name();
  149. QString codec_name;
  150. if (encoding())
  151. codec_name = QLatin1String(encoding()->name());
  152. rDebug.nospace() << "FileAppender("
  153. << "name:" << name() << " "
  154. << "appendfile:" << appendFile() << " "
  155. << "bufferedio:" << bufferedIo() << " "
  156. << "encoding:" << codec_name << " "
  157. << "file:" << file() << " "
  158. << "filter:" << firstFilter() << " "
  159. << "immediateflush:" << immediateFlush() << " "
  160. << "isactive:" << isActive() << " "
  161. << "isclosed:" << isClosed() << " "
  162. << "layout:" << layout_name << " "
  163. << "referencecount:" << referenceCount() << " "
  164. << "threshold:" << threshold().toString() << " "
  165. << "writer:" << writer()
  166. << ")";
  167. return rDebug.space();
  168. }
  169. #endif // QT_NO_DEBUG_STREAM
  170. bool FileAppender::handleIoErrors() const
  171. {
  172. // Q_ASSERT_X(, "FileAppender::handleIoErrors()", "Lock must be held by caller")
  173. if (mpFile->error() == QFile::NoError)
  174. return false;
  175. LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to write to file '%1' for appender '%2'"),
  176. APPENDER_WRITING_FILE_ERROR);
  177. e << mFileName << name();
  178. e.addCausingError(LogError(mpFile->errorString(), mpFile->error()));
  179. logger()->error(e);
  180. return true;
  181. }
  182. void FileAppender::openFile()
  183. {
  184. Q_ASSERT_X(mpFile == 0 && mpTextStream == 0, "FileAppender::openFile()", "Opening file without closing previous file");
  185. QFileInfo file_info(mFileName);
  186. QDir parent_dir = file_info.dir();
  187. if (!parent_dir.exists())
  188. {
  189. logger()->trace("Creating missing parent directory for file %1", mFileName);
  190. QString name = parent_dir.dirName();
  191. parent_dir.cdUp();
  192. parent_dir.mkdir(name);
  193. }
  194. mpFile = new QFile(mFileName);
  195. QFile::OpenMode mode = QIODevice::WriteOnly | QIODevice::Text;
  196. if (mAppendFile)
  197. mode |= QIODevice::Append;
  198. else
  199. mode |= QIODevice::Truncate;
  200. if (!mBufferedIo)
  201. mode |= QIODevice::Unbuffered;
  202. if (!mpFile->open(mode))
  203. {
  204. LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to open file '%1' for appender '%2'"),
  205. APPENDER_OPENING_FILE_ERROR);
  206. e << mFileName << name();
  207. e.addCausingError(LogError(mpFile->errorString(), mpFile->error()));
  208. logger()->error(e);
  209. return;
  210. }
  211. mpTextStream = new QTextStream(mpFile);
  212. setWriter(mpTextStream);
  213. logger()->debug("Opened file '%1' for appender '%2'", mpFile->fileName(), name());
  214. }
  215. bool FileAppender::removeFile(QFile &rFile) const
  216. {
  217. if (rFile.remove())
  218. return true;
  219. LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to remove file '%1' for appender '%2'"),
  220. APPENDER_REMOVE_FILE_ERROR);
  221. e << rFile.fileName() << name();
  222. e.addCausingError(LogError(rFile.errorString(), rFile.error()));
  223. logger()->error(e);
  224. return false;
  225. }
  226. bool FileAppender::renameFile(QFile &rFile,
  227. const QString &rFileName) const
  228. {
  229. logger()->debug("Renaming file '%1' to '%2'", rFile.fileName(), rFileName);
  230. if (rFile.rename(rFileName))
  231. return true;
  232. LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to rename file '%1' to '%2' for appender '%3'"),
  233. APPENDER_RENAMING_FILE_ERROR);
  234. e << rFile.fileName() << rFileName << name();
  235. e.addCausingError(LogError(rFile.errorString(), rFile.error()));
  236. logger()->error(e);
  237. return false;
  238. }
  239. /**************************************************************************
  240. * Implementation: Operators, Helper
  241. **************************************************************************/
  242. } // namespace Log4Qt