Coverage Report

Created: 2025-10-13 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/logging-log4cxx/src/main/cpp/xmllayout.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/logstring.h>
19
#include <log4cxx/xml/xmllayout.h>
20
#include <log4cxx/spi/loggingevent.h>
21
#include <log4cxx/helpers/optionconverter.h>
22
#include <log4cxx/level.h>
23
#include <log4cxx/helpers/transform.h>
24
#include <log4cxx/helpers/iso8601dateformat.h>
25
#include <log4cxx/helpers/stringhelper.h>
26
#include <log4cxx/helpers/transcoder.h>
27
#include <log4cxx/ndc.h>
28
29
30
using namespace LOG4CXX_NS;
31
using namespace LOG4CXX_NS::helpers;
32
using namespace LOG4CXX_NS::spi;
33
using namespace LOG4CXX_NS::xml;
34
35
struct XMLLayout::XMLLayoutPrivate
36
{
37
  XMLLayoutPrivate()
38
0
    : locationInfo(false)
39
0
    , properties(false)
40
0
    , expectedPatternLength(100)
41
0
    {}
42
43
  // Print no location info by default
44
  bool locationInfo; //= false
45
  bool properties; // = false
46
47
  // Expected length of a formatted event excluding the message text
48
  size_t expectedPatternLength;
49
};
50
51
IMPLEMENT_LOG4CXX_OBJECT(XMLLayout)
52
53
XMLLayout::XMLLayout()
54
0
  : m_priv(std::make_unique<XMLLayoutPrivate>())
55
0
{
56
0
  m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
57
0
}
Unexecuted instantiation: log4cxx::xml::XMLLayout::XMLLayout()
Unexecuted instantiation: log4cxx::xml::XMLLayout::XMLLayout()
58
59
0
XMLLayout::~XMLLayout() {}
60
61
void XMLLayout::setOption(const LogString& option,
62
  const LogString& value)
63
0
{
64
0
  if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("LOCATIONINFO"), LOG4CXX_STR("locationinfo")))
65
0
  {
66
0
    setLocationInfo(OptionConverter::toBoolean(value, false));
67
0
    m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
68
0
  }
69
70
0
  if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("PROPERTIES"), LOG4CXX_STR("properties")))
71
0
  {
72
0
    setProperties(OptionConverter::toBoolean(value, false));
73
0
    m_priv->expectedPatternLength = getFormattedEventCharacterCount() * 2;
74
0
  }
75
0
}
76
77
void XMLLayout::format(LogString& output,
78
  const spi::LoggingEventPtr& event,
79
  Pool& p) const
80
0
{
81
0
  auto& lsMsg = event->getRenderedMessage();
82
0
  output.reserve(m_priv->expectedPatternLength + lsMsg.size());
83
0
  output.append(LOG4CXX_STR("<log4j:event logger=\""));
84
0
  Transform::appendEscapingTags(output, event->getLoggerName());
85
0
  output.append(LOG4CXX_STR("\" timestamp=\""));
86
0
  StringHelper::toString(event->getTimeStamp() / 1000L, p, output);
87
0
  output.append(LOG4CXX_STR("\" level=\""));
88
0
  Transform::appendEscapingTags(output, event->getLevel()->toString());
89
0
  output.append(LOG4CXX_STR("\" thread=\""));
90
0
  Transform::appendEscapingTags(output, event->getThreadName());
91
0
  output.append(LOG4CXX_STR("\">"));
92
0
  output.append(LOG4CXX_EOL);
93
94
0
  output.append(LOG4CXX_STR("<log4j:message><![CDATA["));
95
  // Append the rendered message. Also make sure to escape any
96
  // existing CDATA sections.
97
0
  Transform::appendEscapingCDATA(output, lsMsg);
98
0
  output.append(LOG4CXX_STR("]]></log4j:message>"));
99
0
  output.append(LOG4CXX_EOL);
100
101
0
  LogString ndc;
102
103
0
  if (event->getNDC(ndc))
104
0
  {
105
0
    output.append(LOG4CXX_STR("<log4j:NDC><![CDATA["));
106
0
    Transform::appendEscapingCDATA(output, ndc);
107
0
    output.append(LOG4CXX_STR("]]></log4j:NDC>"));
108
0
    output.append(LOG4CXX_EOL);
109
0
  }
110
111
0
  if (m_priv->locationInfo)
112
0
  {
113
0
    output.append(LOG4CXX_STR("<log4j:locationInfo class=\""));
114
0
    const LocationInfo& locInfo = event->getLocationInformation();
115
0
    LOG4CXX_DECODE_CHAR(className, locInfo.getClassName());
116
0
    Transform::appendEscapingTags(output, className);
117
0
    output.append(LOG4CXX_STR("\" method=\""));
118
0
    LOG4CXX_DECODE_CHAR(method, locInfo.getMethodName());
119
0
    Transform::appendEscapingTags(output, method);
120
0
    output.append(LOG4CXX_STR("\" file=\""));
121
0
    LOG4CXX_DECODE_CHAR(fileName, locInfo.getFileName());
122
0
    Transform::appendEscapingTags(output, fileName);
123
0
    output.append(LOG4CXX_STR("\" line=\""));
124
0
    StringHelper::toString(locInfo.getLineNumber(), p, output);
125
0
    output.append(LOG4CXX_STR("\"/>"));
126
0
    output.append(LOG4CXX_EOL);
127
0
  }
128
129
0
  if (m_priv->properties)
130
0
  {
131
0
    LoggingEvent::KeySet propertySet(event->getPropertyKeySet());
132
0
    LoggingEvent::KeySet keySet(event->getMDCKeySet());
133
134
0
    if (!(keySet.empty() && propertySet.empty()))
135
0
    {
136
0
      output.append(LOG4CXX_STR("<log4j:properties>"));
137
0
      output.append(LOG4CXX_EOL);
138
139
0
      for (auto key : keySet)
140
0
      {
141
0
        LogString value;
142
143
0
        if (event->getMDC(key, value))
144
0
        {
145
0
          output.append(LOG4CXX_STR("<log4j:data name=\""));
146
0
          Transform::appendEscapingTags(output, key);
147
0
          output.append(LOG4CXX_STR("\" value=\""));
148
0
          Transform::appendEscapingTags(output, value);
149
0
          output.append(LOG4CXX_STR("\"/>"));
150
0
          output.append(LOG4CXX_EOL);
151
0
        }
152
0
      }
153
154
0
      for (auto key : propertySet)
155
0
      {
156
0
        LogString value;
157
158
0
        if (event->getProperty(key, value))
159
0
        {
160
0
          output.append(LOG4CXX_STR("<log4j:data name=\""));
161
0
          Transform::appendEscapingTags(output, key);
162
0
          output.append(LOG4CXX_STR("\" value=\""));
163
0
          Transform::appendEscapingTags(output, value);
164
0
          output.append(LOG4CXX_STR("\"/>"));
165
0
          output.append(LOG4CXX_EOL);
166
0
        }
167
0
      }
168
169
0
      output.append(LOG4CXX_STR("</log4j:properties>"));
170
0
      output.append(LOG4CXX_EOL);
171
0
    }
172
0
  }
173
174
0
  output.append(LOG4CXX_STR("</log4j:event>"));
175
0
  output.append(LOG4CXX_EOL);
176
0
  output.append(LOG4CXX_EOL);
177
0
}
178
179
void XMLLayout::setLocationInfo(bool locationInfo1)
180
0
{
181
0
  m_priv->locationInfo = locationInfo1;
182
0
}
183
184
bool XMLLayout::getLocationInfo() const
185
0
{
186
0
  return m_priv->locationInfo;
187
0
}
188
189
void XMLLayout::setProperties(bool flag)
190
0
{
191
0
  m_priv->properties = flag;
192
0
}
193
194
bool XMLLayout::getProperties()
195
0
{
196
0
  return m_priv->properties;
197
0
}
198