Coverage Report

Created: 2026-06-15 06:22

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
63.1k
#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
461
  : AppenderSkeleton (std::move(priv))
61
461
{
62
63
461
}
log4cxx::WriterAppender::WriterAppender(std::__1::unique_ptr<log4cxx::WriterAppender::WriterAppenderPriv, std::__1::default_delete<log4cxx::WriterAppender::WriterAppenderPriv> >)
Line
Count
Source
60
461
  : AppenderSkeleton (std::move(priv))
61
461
{
62
63
461
}
Unexecuted instantiation: log4cxx::WriterAppender::WriterAppender(std::__1::unique_ptr<log4cxx::WriterAppender::WriterAppenderPriv, std::__1::default_delete<log4cxx::WriterAppender::WriterAppenderPriv> >)
64
65
WriterAppender::~WriterAppender()
66
461
{
67
461
  if (_priv->setClosed())
68
0
    _priv->close();
69
461
}
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
922
{
78
922
  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
922
  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
922
}
90
91
void WriterAppender::append( LOG4CXX_APPEND_FORMAL_PARAMETERS )
92
4.61k
{
93
94
4.61k
  if (!checkEntryConditions())
95
0
  {
96
0
    return;
97
0
  }
98
99
4.61k
  subAppend( LOG4CXX_APPEND_PARAMETERS );
100
4.61k
}
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
4.61k
{
110
4.61k
  return _priv->checkWriter() && _priv->checkLayout() && _priv->checkNotClosed();
111
4.61k
}
112
113
bool WriterAppender::WriterAppenderPriv::checkWriter()
114
4.61k
{
115
4.61k
  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
4.61k
  return true;
127
4.61k
}
128
129
void WriterAppender::close()
130
461
{
131
461
  if (_priv->setClosed())
132
461
    _priv->close();
133
461
}
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
1.38k
{
147
1.38k
  if (this->writer != NULL)
148
925
  {
149
925
    try
150
925
    {
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
925
      this->writeFooter();
157
925
      this->writer->close();
158
925
      this->writer = 0;
159
925
    }
160
925
    catch (IOException& e)
161
925
    {
162
0
      LogLog::warn(LOG4CXX_STR("Could not close writer for WriterAppender named ") + this->name, e);
163
0
    }
164
925
  }
165
166
1.38k
}
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
925
{
176
177
925
  LogString enc(getEncoding());
178
179
925
  CharsetEncoderPtr encoder;
180
181
925
  if (enc.empty())
182
925
  {
183
925
    encoder = CharsetEncoder::getDefaultEncoder();
184
925
  }
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
925
  return std::make_shared<OutputStreamWriter>(os, encoder);
206
925
}
207
208
LogString WriterAppender::getEncoding() const
209
1.85k
{
210
1.85k
  return _priv->encoding;
211
1.85k
}
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
4.61k
{
220
#if ENABLE_FAILING_APPENDER_SIMULATION_TESTING
221
  if (event->getRenderedMessage() == _priv->exceptionTriggeringMessage)
222
    throw RuntimeException(LOG4CXX_STR("Simulated fault"));
223
#endif
224
4.61k
  LogString msg;
225
4.61k
  _priv->layout->format(msg, event);
226
227
4.61k
  if (_priv->writer != NULL)
228
4.61k
  {
229
4.61k
    _priv->writer->write(msg);
230
231
4.61k
    if (_priv->immediateFlush)
232
4.61k
    {
233
4.61k
      _priv->writer->flush();
234
4.61k
    }
235
4.61k
  }
236
4.61k
}
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
925
{
253
925
  if (this->layout != NULL)
254
925
  {
255
925
    LogString foot;
256
925
    this->layout->appendFooter(foot);
257
925
    this->writer->write(foot);
258
925
  }
259
925
}
260
261
void WriterAppender::WriterAppenderPriv::writeHeader()
262
925
{
263
925
  if (this->layout != NULL)
264
925
  {
265
925
    LogString header;
266
925
    this->layout->appendHeader(header);
267
925
    this->writer->write(header);
268
925
  }
269
925
}
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