LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
QsLogDest.cpp
Go to the documentation of this file.
1// Copyright (c) 2010, Razvan Petru
2// SPDX-FileCopyrightText: 2022 CEA LIST <gael.de-chalendar@cea.fr>
3//
4// SPDX-License-Identifier: MIT
5
6// Redistribution and use in source and binary forms, with or without modification,
7// are permitted provided that the following conditions are met:
8
9// * Redistributions of source code must retain the above copyright notice, this
10// list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above copyright notice, this
12// list of conditions and the following disclaimer in the documentation and/or other
13// materials provided with the distribution.
14// * The name of the contributors may not be used to endorse or promote products
15// derived from this software without specific prior written permission.
16
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26// OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "QsLogDest.h"
29#include "QsDebugOutput.h"
30
33#include "common/LimaCommon.h"
34
35#ifdef WIN32
36#pragma warning(disable: 4127)
37#endif
38#include <QFile>
39#include <QTextStream>
40#include <QString>
41#include <QFileInfo>
42#include <QDir>
43#ifdef WIN32
44#pragma warning(enable: 4127)
45#endif
46
47using namespace Lima;
48using namespace Lima::Common::Misc;
49
50namespace QsLogging
51{
52
54{
55public:
57 {
58 }
59 QMap< QString, DestinationPtr > m_destinations;
61 QMap< QString, QString > m_destinationSources;
62
66 QStringList m_configuredFiles;
67};
68
69Destinations::Destinations(QObject* parent) :
70 QObject(parent),
71 d(new DestinationsImpl())
72{
73 connect(&d->m_configFileWatcher,SIGNAL(fileChanged(QString)),
74 this,SLOT(configureFileChanged(QString)));
75}
76
77Destinations::~Destinations()
78{
79 delete d;
80}
81
82const QMap< QString, DestinationPtr >& Destinations::destinations() const
83{
84 return d->m_destinations;
85}
86
87void Destinations::configureFileChanged ( const QString & path )
88{
89 if (QFile(path).exists())
90 {
91 configure(path, true);
92 }
93 else
94 {
95 if (d->m_configuredFiles.contains(path))
96 {
97 d->m_configuredFiles.removeAll(path);
98 }
99 }
100}
101
103{
104// std::cerr << "Destinations::setDefault" << std::endl;
105 d->m_destinations.insert("DefaultOutput",
107 return true;
108}
109
111{
112 d->m_destinations.remove("DefaultOutput");
113 return true;
114}
115
116bool Destinations::configure(const QString& fileName, bool reload)
117{
118 QFile file(fileName);
119 QFileInfo fileInfo(fileName);
120 QDir configDir = fileInfo.dir();
121
122 // std::cerr << "Destinations::configure " << fileName.toStdString() << " " << reload << std::endl;
123
124 if (!file.open(QIODevice::ReadOnly))
125 {
126 std::cerr << "Destinations::configure Unable to open qslog configuration file: \""
127 << fileName.toStdString() << "\"" << std::endl;
128 return false;
129 }
130 if (!reload && d->m_configuredFiles.contains(fileName))
131 {
132 LOGINIT("Logging");
133 LDEBUG << "Destinations::configure configuration file: \""
134 << fileName << "\" already configured";
135 return true;
136 }
137
138 d->m_configFileWatcher.addPath(fileName);
139 d->m_configuredFiles.append(fileName);
140 d->m_configuredFiles.removeDuplicates();
141
142 bool res = true;
143 QTextStream in(&file);
144 QString line = in.readLine();
145 while (!line.isNull())
146 {
147 if (!line.startsWith("#"))
148 {
149 QStringList elts = line.split("=");
150 if (elts.size()>0 && elts.at(0).trimmed().startsWith("log4j.appender."))
151 {
152 auto destination = elts.at(0).trimmed().split(".").last();
153 QString value;
154 if (elts.size()==2)
155 value = elts.at(1).trimmed();
156 if (d->m_destinations.contains(destination))
157 {
158 LOGINIT("Logging");
159 LDEBUG << fileName << "overwrites destination definition"
160 << destination << "from"
161 << d->m_destinationSources[destination];
162 }
163 if (destination == "DebugOutput")
164 {
165 d->m_destinationSources.insert(destination, fileName);
166 d->m_destinations.insert(destination,
168 d->m_destinations.remove("DefaultOutput");
169 }
170 else if (destination == "File")
171 {
172 d->m_destinationSources.insert(destination, fileName);
173 d->m_destinations.insert(destination,
175 }
176 else
177 {
178 std::cerr << "Error reading \"" << fileName.toUtf8().constData()
179 << "\": unknown destination \""
180 << destination.toUtf8().constData()
181 << std::endl;
182 res = false;
183 }
184 }
185 else if (elts.size()==2 && elts.at(0).trimmed() == "include")
186 {
187 QString includedFileName = elts.at(1).trimmed();
188 QString includedInitFileName = includedFileName;
189 if (!QFileInfo(includedInitFileName).isAbsolute())
190 {
191 includedInitFileName = configDir.filePath(includedInitFileName);
192 }
193 res &= configure(includedInitFileName);
194 }
195 }
196 line = in.readLine();
197 }
198 return res;
199}
200
201
204{
205public:
206 FileDestination(const QString& filePath);
207 virtual void write(const QString& message, const QString& zone = "") override;
208
209private:
210 QFile mFile;
211 QTextStream mOutputStream;
212};
213
214
215FileDestination::FileDestination(const QString& filePath)
216{
217 mFile.setFileName(filePath);
218 mFile.open(QFile::WriteOnly|QFile::Append); //fixme: should throw on failure
219 // std::cerr << "FileDestination::FileDestination "
220 // << QFileInfo(mFile).absoluteFilePath().toUtf8().constData()
221 // << std::endl;
222 mOutputStream.setDevice(&mFile);
223}
224
225void FileDestination::write(const QString& message, const QString& zone)
226{
227 // std::cerr << "FileDestination::write " << zone.toStdString() << " " << message.toStdString() << std::endl;
228 if (!zone.isEmpty())
229 mOutputStream << " : " << zone << " : ";
230 mOutputStream << message << QTENDL;
231 mOutputStream.flush();
232}
233
234void DebugOutputDestination::write(const QString& message, const QString& zone)
235{
236 // std::cerr << "DebugOutputDestination::write " << zone.toStdString() << " " << message.toStdString() << std::endl;
237 if (!zone.isEmpty())
238 QsDebugOutput::output(QString(QLatin1String(" : %1 : %2")).arg(zone, message));
239 else
240 QsDebugOutput::output(message);
241}
242
244{
245 // std::cerr << "DestinationFactory::MakeFileDestination " << filePath.toStdString() << std::endl;
246 return DestinationPtr(new FileDestination(filePath));
247}
248
250{
251 // std::cerr << "DestinationFactory::MakeDebugOutputDestination" << std::endl;
253}
254
255} // end namespace
256
#define QTENDL
Definition LimaCommon.h:32
#define LOGINIT(X)
Definition LimaCommon.h:187
#define LDEBUG
Definition LimaCommon.h:157
LimaFileSystemWatcher extends QFileSystemWatcher to work on replaced files
void addPath(const QString &path)
static void output(const QString &a_message)
virtual void write(const QString &message, const QString &zone=QLatin1String("")) override
static DestinationPtr MakeDebugOutputDestination()
static DestinationPtr MakeFileDestination(const QString &filePath)
QMap< QString, QString > m_destinationSources
Association destination name / file name. Allows to inform of overwrites.
Definition QsLogDest.cpp:61
QMap< QString, DestinationPtr > m_destinations
Definition QsLogDest.cpp:59
LimaFileSystemWatcher m_configFileWatcher
Definition QsLogDest.cpp:63
QStringList m_configuredFiles
Store the list of configuration files already loaded.
Definition QsLogDest.cpp:66
bool configure(const QString &fileName, bool reload=false)
const QMap< QString, DestinationPtr > & destinations() const
Definition QsLogDest.cpp:82
FileDestination(const QString &filePath)
virtual void write(const QString &message, const QString &zone="") override
NAUTITIA.
std::shared_ptr< Destination > DestinationPtr
Definition QsLog.cpp:47