Coverage Report

Created: 2025-07-01 06:08

/src/logging-log4cxx/src/main/cpp/xmllayout.cpp
Line
Count
Source (jump to first uncovered line)
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
  output.reserve(m_priv->expectedPatternLength + event->getMessage().size());
82
0
  output.append(LOG4CXX_STR("<log4j:event logger=\""));
83
0
  Transform::appendEscapingTags(output, event->getLoggerName());
84
0
  output.append(LOG4CXX_STR("\" timestamp=\""));
85
0
  StringHelper::toString(event->getTimeStamp() / 1000L, p, output);
86
0
  output.append(LOG4CXX_STR("\" level=\""));
87
0
  Transform::appendEscapingTags(output, event->getLevel()->toString());
88
0
  output.append(LOG4CXX_STR("\" thread=\""));
89
0
  Transform::appendEscapingTags(output, event->getThreadName());
90
0
  output.append(LOG4CXX_STR("\">"));
91
0
  output.append(LOG4CXX_EOL);
92
93
0
  output.append(LOG4CXX_STR("<log4j:message><![CDATA["));
94
  // Append the rendered message. Also make sure to escape any
95
  // existing CDATA sections.
96
0
  Transform::appendEscapingCDATA(output, event->getRenderedMessage());
97
0
  output.append(LOG4CXX_STR("]]></log4j:message>"));
98
0
  output.append(LOG4CXX_EOL);
99
100
0
  LogString ndc;
101
102
0
  if (event->getNDC(ndc))
103
0
  {
104
0
    output.append(LOG4CXX_STR("<log4j:NDC><![CDATA["));
105
0
    Transform::appendEscapingCDATA(output, ndc);
106
0
    output.append(LOG4CXX_STR("]]></log4j:NDC>"));
107
0
    output.append(LOG4CXX_EOL);
108
0
  }
109
110
0
  if (m_priv->locationInfo)
111
0
  {
112
0
    output.append(LOG4CXX_STR("<log4j:locationInfo class=\""));
113
0
    const LocationInfo& locInfo = event->getLocationInformation();
114
0
    LOG4CXX_DECODE_CHAR(className, locInfo.getClassName());
115
0
    Transform::appendEscapingTags(output, className);
116
0
    output.append(LOG4CXX_STR("\" method=\""));
117
0
    LOG4CXX_DECODE_CHAR(method, locInfo.getMethodName());
118
0
    Transform::appendEscapingTags(output, method);
119
0
    output.append(LOG4CXX_STR("\" file=\""));
120
0
    LOG4CXX_DECODE_CHAR(fileName, locInfo.getFileName());
121
0
    Transform::appendEscapingTags(output, fileName);
122
0
    output.append(LOG4CXX_STR("\" line=\""));
123
0
    StringHelper::toString(locInfo.getLineNumber(), p, output);
124
0
    output.append(LOG4CXX_STR("\"/>"));
125
0
    output.append(LOG4CXX_EOL);
126
0
  }
127
128
0
  if (m_priv->properties)
129
0
  {
130
0
    LoggingEvent::KeySet propertySet(event->getPropertyKeySet());
131
0
    LoggingEvent::KeySet keySet(event->getMDCKeySet());
132
133
0
    if (!(keySet.empty() && propertySet.empty()))
134
0
    {
135
0
      output.append(LOG4CXX_STR("<log4j:properties>"));
136
0
      output.append(LOG4CXX_EOL);
137
138
0
      for (auto key : keySet)
139
0
      {
140
0
        LogString value;
141
142
0
        if (event->getMDC(key, value))
143
0
        {
144
0
          output.append(LOG4CXX_STR("<log4j:data name=\""));
145
0
          Transform::appendEscapingTags(output, key);
146
0
          output.append(LOG4CXX_STR("\" value=\""));
147
0
          Transform::appendEscapingTags(output, value);
148
0
          output.append(LOG4CXX_STR("\"/>"));
149
0
          output.append(LOG4CXX_EOL);
150
0
        }
151
0
      }
152
153
0
      for (auto key : propertySet)
154
0
      {
155
0
        LogString value;
156
157
0
        if (event->getProperty(key, value))
158
0
        {
159
0
          output.append(LOG4CXX_STR("<log4j:data name=\""));
160
0
          Transform::appendEscapingTags(output, key);
161
0
          output.append(LOG4CXX_STR("\" value=\""));
162
0
          Transform::appendEscapingTags(output, value);
163
0
          output.append(LOG4CXX_STR("\"/>"));
164
0
          output.append(LOG4CXX_EOL);
165
0
        }
166
0
      }
167
168
0
      output.append(LOG4CXX_STR("</log4j:properties>"));
169
0
      output.append(LOG4CXX_EOL);
170
0
    }
171
0
  }
172
173
0
  output.append(LOG4CXX_STR("</log4j:event>"));
174
0
  output.append(LOG4CXX_EOL);
175
0
  output.append(LOG4CXX_EOL);
176
0
}
177
178
void XMLLayout::setLocationInfo(bool locationInfo1)
179
0
{
180
0
  m_priv->locationInfo = locationInfo1;
181
0
}
182
183
bool XMLLayout::getLocationInfo() const
184
0
{
185
0
  return m_priv->locationInfo;
186
0
}
187
188
void XMLLayout::setProperties(bool flag)
189
0
{
190
0
  m_priv->properties = flag;
191
0
}
192
193
bool XMLLayout::getProperties()
194
0
{
195
0
  return m_priv->properties;
196
0
}
197