Coverage Report

Created: 2026-05-30 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/logging-log4cxx/src/main/cpp/writerappender.cpp
Line
Count
Source
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
#include <log4cxx/writerappender.h>
19
#include <log4cxx/helpers/loglog.h>
20
#include <log4cxx/layout.h>
21
#include <log4cxx/helpers/stringhelper.h>
22
#include <log4cxx/private/appenderskeleton_priv.h>
23
#include <log4cxx/private/writerappender_priv.h>
24
#include <mutex>
25
26
using namespace LOG4CXX_NS;
27
using namespace LOG4CXX_NS::helpers;
28
using namespace LOG4CXX_NS::spi;
29
30
0
#define _priv static_cast<WriterAppenderPriv*>(m_priv.get())
31
32
IMPLEMENT_LOG4CXX_OBJECT(WriterAppender)
33
34
WriterAppender::WriterAppender() :
35
0
  AppenderSkeleton (std::make_unique<WriterAppenderPriv>())
36
0
{
37
0
}
Unexecuted instantiation: log4cxx::WriterAppender::WriterAppender()
Unexecuted instantiation: log4cxx::WriterAppender::WriterAppender()
38
39
#if LOG4CXX_ABI_VERSION <= 15
40
WriterAppender::WriterAppender(const LayoutPtr& layout, helpers::WriterPtr& writer)
41
0
  : AppenderSkeleton (std::make_unique<WriterAppenderPriv>(layout, writer))
42
0
{
43
0
  Pool p;
44
0
  activateOptions(p);
45
0
}
Unexecuted instantiation: log4cxx::WriterAppender::WriterAppender(std::__1::shared_ptr<log4cxx::Layout> const&, std::__1::shared_ptr<log4cxx::helpers::Writer>&)
Unexecuted instantiation: log4cxx::WriterAppender::WriterAppender(std::__1::shared_ptr<log4cxx::Layout> const&, std::__1::shared_ptr<log4cxx::helpers::Writer>&)
46
47
WriterAppender::WriterAppender(const LayoutPtr& layout)
48
0
  : AppenderSkeleton (std::make_unique<WriterAppenderPriv>(layout))
49
0
{
50
0
}
Unexecuted instantiation: log4cxx::WriterAppender::WriterAppender(std::__1::shared_ptr<log4cxx::Layout> const&)
Unexecuted instantiation: log4cxx::WriterAppender::WriterAppender(std::__1::shared_ptr<log4cxx::Layout> const&)
51
#else
52
WriterAppender::WriterAppender(const LayoutPtr& layout, const helpers::WriterPtr& writer)
53
  : AppenderSkeleton(std::make_unique<WriterAppenderPriv>(layout, writer))
54
{
55
  activateOptions();
56
}
57
#endif
58
59
WriterAppender::WriterAppender(std::unique_ptr<WriterAppenderPriv> priv)
60
0
  : AppenderSkeleton (std::move(priv))
61
0
{
62
63
0
}
Unexecuted instantiation: log4cxx::WriterAppender::WriterAppender(std::__1::unique_ptr<log4cxx::WriterAppender::WriterAppenderPriv, std::__1::default_delete<log4cxx::WriterAppender::WriterAppenderPriv> >)
Unexecuted instantiation: log4cxx::WriterAppender::WriterAppender(std::__1::unique_ptr<log4cxx::WriterAppender::WriterAppenderPriv, std::__1::default_delete<log4cxx::WriterAppender::WriterAppenderPriv> >)
64
65
WriterAppender::~WriterAppender()
66
0
{
67
0
  if (_priv->setClosed())
68
0
    _priv->close();
69
0
}
70
71
void WriterAppender::activateOptions( LOG4CXX_ACTIVATE_OPTIONS_FORMAL_PARAMETERS )
72
0
{
73
0
  _priv->activateOptions();
74
0
}
75
76
void WriterAppender::WriterAppenderPriv::activateOptions()
77
0
{
78
0
  if (this->layout == 0)
79
0
  {
80
0
    this->errorHandler->error(LOG4CXX_STR("No layout set for the appender named [")
81
0
      + this->name + LOG4CXX_STR("]."));
82
0
  }
83
84
0
  if (this->writer == 0)
85
0
  {
86
0
    this->errorHandler->error(LOG4CXX_STR("No writer set for the appender named [")
87
0
      + this->name + LOG4CXX_STR("]."));
88
0
  }
89
0
}
90
91
void WriterAppender::append( LOG4CXX_APPEND_FORMAL_PARAMETERS )
92
0
{
93
94
0
  if (!checkEntryConditions())
95
0
  {
96
0
    return;
97
0
  }
98
99
0
  subAppend( LOG4CXX_APPEND_PARAMETERS );
100
0
}
101
102
/**
103
   This method determines if there is a sense in attempting to append.
104
105
   <p>It checks whether there is a set output target and also if
106
   there is a set layout. If these checks fail, then the boolean
107
   value <code>false</code> is returned. */
108
bool WriterAppender::checkEntryConditions() const
109
0
{
110
0
  return _priv->checkWriter() && _priv->checkLayout() && _priv->checkNotClosed();
111
0
}
112
113
bool WriterAppender::WriterAppenderPriv::checkWriter()
114
0
{
115
0
  if (this->writer == 0)
116
0
  {
117
0
    if (!this->warnedNoWriter)
118
0
    {
119
0
      this->errorHandler->error(
120
0
        LogString(LOG4CXX_STR("No output stream or file set for the appender named [")) +
121
0
        this->name + LOG4CXX_STR("]."));
122
0
      this->warnedNoWriter = true;
123
0
    }
124
0
    return false;
125
0
  }
126
0
  return true;
127
0
}
128
129
void WriterAppender::close()
130
0
{
131
0
  if (_priv->setClosed())
132
0
    _priv->close();
133
0
}
134
135
#if LOG4CXX_ABI_VERSION <= 15
136
/**
137
 * Close the underlying {@link java.io.Writer}.
138
 * */
139
void WriterAppender::closeWriter()
140
0
{
141
0
   _priv->close();
142
0
}
143
#endif
144
145
void WriterAppender::WriterAppenderPriv::close()
146
0
{
147
0
  if (this->writer != NULL)
148
0
  {
149
0
    try
150
0
    {
151
      // before closing we have to output out layout's footer
152
      //
153
      //   Using the object's pool since this is a one-shot operation
154
      //    and pool is likely to be reclaimed soon when appender is destructed.
155
      //
156
0
      this->writeFooter();
157
0
      this->writer->close();
158
0
      this->writer = 0;
159
0
    }
160
0
    catch (IOException& e)
161
0
    {
162
0
      LogLog::warn(LOG4CXX_STR("Could not close writer for WriterAppender named ") + this->name, e);
163
0
    }
164
0
  }
165
166
0
}
167
168
/**
169
   Returns an OutputStreamWriter when passed an OutputStream.  The
170
   encoding used will depend on the value of the
171
   <code>encoding</code> property.  If the encoding value is
172
   specified incorrectly the writer will be opened using the default
173
   system encoding (an error message will be printed to the loglog.  */
174
WriterPtr WriterAppender::createWriter(LOG4CXX_16_CONST OutputStreamPtr& os)
175
0
{
176
177
0
  LogString enc(getEncoding());
178
179
0
  CharsetEncoderPtr encoder;
180
181
0
  if (enc.empty())
182
0
  {
183
0
    encoder = CharsetEncoder::getDefaultEncoder();
184
0
  }
185
0
  else
186
0
  {
187
0
    if (StringHelper::equalsIgnoreCase(enc,
188
0
        LOG4CXX_STR("utf-16"), LOG4CXX_STR("UTF-16")))
189
0
    {
190
0
      encoder = CharsetEncoder::getEncoder(LOG4CXX_STR("UTF-16BE"));
191
0
    }
192
0
    else
193
0
    {
194
0
      encoder = CharsetEncoder::getEncoder(enc);
195
0
    }
196
197
0
    if (encoder == NULL)
198
0
    {
199
0
      encoder = CharsetEncoder::getDefaultEncoder();
200
0
      LogLog::warn(LOG4CXX_STR("Error initializing output writer."));
201
0
      LogLog::warn(LOG4CXX_STR("Unsupported encoding?"));
202
0
    }
203
0
  }
204
205
0
  return std::make_shared<OutputStreamWriter>(os, encoder);
206
0
}
207
208
LogString WriterAppender::getEncoding() const
209
0
{
210
0
  return _priv->encoding;
211
0
}
212
213
void WriterAppender::setEncoding(const LogString& enc)
214
0
{
215
0
  _priv->encoding = enc;
216
0
}
217
218
void WriterAppender::subAppend( LOG4CXX_APPEND_FORMAL_PARAMETERS )
219
0
{
220
#if ENABLE_FAILING_APPENDER_SIMULATION_TESTING
221
  if (event->getRenderedMessage() == _priv->exceptionTriggeringMessage)
222
    throw RuntimeException(LOG4CXX_STR("Simulated fault"));
223
#endif
224
0
  LogString msg;
225
0
  _priv->layout->format(msg, event);
226
227
0
  if (_priv->writer != NULL)
228
0
  {
229
0
    _priv->writer->write(msg);
230
231
0
    if (_priv->immediateFlush)
232
0
    {
233
0
      _priv->writer->flush();
234
0
    }
235
0
  }
236
0
}
237
238
239
#if LOG4CXX_ABI_VERSION <= 15
240
void WriterAppender::writeHeader(Pool& p)
241
0
{
242
0
  _priv->writeHeader();
243
0
}
244
245
void WriterAppender::writeFooter(Pool& p)
246
0
{
247
0
  _priv->writeFooter();
248
0
}
249
#endif
250
251
void WriterAppender::WriterAppenderPriv::writeFooter()
252
0
{
253
0
  if (this->layout != NULL)
254
0
  {
255
0
    LogString foot;
256
0
    this->layout->appendFooter(foot);
257
0
    this->writer->write(foot);
258
0
  }
259
0
}
260
261
void WriterAppender::WriterAppenderPriv::writeHeader()
262
0
{
263
0
  if (this->layout != NULL)
264
0
  {
265
0
    LogString header;
266
0
    this->layout->appendHeader(header);
267
0
    this->writer->write(header);
268
0
  }
269
0
}
270
271
272
#if LOG4CXX_ABI_VERSION <= 15
273
void WriterAppender::setWriter(const WriterPtr& newWriter)
274
0
{
275
0
  _priv->setWriter(newWriter);
276
0
}
277
278
void WriterAppender::setWriterInternal(const WriterPtr& newWriter)
279
0
{
280
0
  _priv->writer = newWriter;
281
0
}
282
#endif
283
284
bool WriterAppender::requiresLayout() const
285
0
{
286
0
  return true;
287
0
}
288
289
void WriterAppender::setOption(const LogString& option, const LogString& value)
290
0
{
291
0
  if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("ENCODING"), LOG4CXX_STR("encoding")))
292
0
  {
293
0
    setEncoding(value);
294
0
  }
295
0
  else
296
0
  {
297
0
    AppenderSkeleton::setOption(option, value);
298
0
  }
299
0
}
300
301
302
void WriterAppender::setImmediateFlush(bool value)
303
0
{
304
0
  _priv->immediateFlush = value;
305
0
}
306
307
bool WriterAppender::getImmediateFlush() const
308
0
{
309
0
  return _priv->immediateFlush;
310
0
}
311
312
#if LOG4CXX_ABI_VERSION <= 15
313
0
const LOG4CXX_NS::helpers::WriterPtr WriterAppender::getWriter() const{
314
0
  return _priv->writer;
315
0
}
316
#endif