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/include/log4cxx/hierarchy.h
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
#ifndef _LOG4CXX_HIERARCHY_H
19
#define _LOG4CXX_HIERARCHY_H
20
21
22
#include <log4cxx/spi/loggerrepository.h>
23
#include <log4cxx/spi/loggerfactory.h>
24
#include <log4cxx/provisionnode.h>
25
#include <log4cxx/spi/hierarchyeventlistener.h>
26
27
namespace LOG4CXX_NS
28
{
29
30
class Hierarchy;
31
LOG4CXX_PTR_DEF(Hierarchy);
32
33
/**
34
This class is specialized in retrieving loggers by name and also
35
maintaining the logger hierarchy.
36
37
<p><em>The casual user does not have to deal with this class
38
directly.</em>
39
40
<p>The structure of the logger hierarchy is maintained by the
41
#getLogger method. The hierarchy is such that children link
42
to their parent but parents do not have any pointers to their
43
children. Moreover, loggers can be instantiated in any order, in
44
particular descendant before ancestor.
45
46
<p>In case a descendant is created before a particular ancestor,
47
then it creates a provision node for the ancestor and adds itself
48
to the provision node. Other descendants of the same ancestor add
49
themselves to the previously created provision node.
50
*/
51
class LOG4CXX_EXPORT Hierarchy : public spi::LoggerRepository
52
{
53
  private:
54
    LOG4CXX_DECLARE_PRIVATE_MEMBER_PTR(HierarchyPrivate, m_priv)
55
56
  public:
57
    DECLARE_ABSTRACT_LOG4CXX_OBJECT(Hierarchy)
58
0
    BEGIN_LOG4CXX_CAST_MAP()
59
#if 15 < LOG4CXX_ABI_VERSION
60
    LOG4CXX_CAST_ENTRY(Hierarchy)
61
    LOG4CXX_CAST_ENTRY_CHAIN(spi::LoggerRepository)
62
#else
63
0
    LOG4CXX_CAST_ENTRY(spi::LoggerRepository)
64
0
#endif
65
0
    END_LOG4CXX_CAST_MAP()
66
67
  private:
68
    /**
69
    Create a new logger hierarchy.
70
    */
71
    Hierarchy();
72
73
  public:
74
    static HierarchyPtr create();
75
76
    ~Hierarchy();
77
78
    void addHierarchyEventListener(const spi::HierarchyEventListenerPtr& listener) override;
79
80
    /**
81
     * Remove a previously added HierarchyEventListener.
82
     *
83
     */
84
#if LOG4CXX_ABI_VERSION <= 15
85
    void removeHierarchyEventListener(const spi::HierarchyEventListenerPtr& listener);
86
#else
87
    void removeHierarchyEventListener(const spi::HierarchyEventListenerPtr& listener) override;
88
#endif
89
90
    /**
91
     * Call \c configurator if not yet configured and \c configurator has not already been tried.
92
     * If \c configurator succeeds, it must call LoggerRepository::setConfigured
93
     * to ensure subsequent calls to LoggerRepository::ensureIsConfigured
94
     * from overwriting the configuration.
95
     */
96
    void ensureIsConfigured(std::function<void()> configurator) override;
97
98
    /**
99
    This call will clear all logger definitions from the internal
100
    hashtable. Invoking this method will irrevocably mess up the
101
    logger hierarchy.
102
103
    <p>You should <em>really</em> know what you are doing before
104
    invoking this method.
105
    */
106
    void clear();
107
108
    void emitNoAppenderWarning(const Logger* logger) override;
109
110
    /**
111
    Check if the named logger exists in the hierarchy. If so return
112
    its reference, otherwise returns <code>null</code>.
113
114
      @param name The name of the logger to search for.
115
116
    */
117
    LoggerPtr exists(const LogString& name) override;
118
119
    /**
120
    The string form of {@link #setThreshold(const LevelPtr&) setThreshold}.
121
    */
122
    void setThreshold(const LogString& levelStr) override;
123
124
    /**
125
    Enable logging for logging requests with level <code>newLevel</code> or
126
    higher. By default all levels are enabled.
127
128
    @param newLevel The minimum level of logging requests that are sent to appenders.
129
    */
130
    void setThreshold(const LevelPtr& newLevel) override;
131
132
    void fireAddAppenderEvent(const Logger* logger, const Appender* appender) override;
133
134
    void fireRemoveAppenderEvent(const Logger* logger, const Appender* appender) override;
135
136
    /**
137
    Returns a Level representation of the <code>enable</code>
138
    state.
139
    */
140
    LevelPtr getThreshold() const override;
141
142
    /**
143
    Retrieve the \c name Logger instance using
144
    the default factory to create it if required.
145
146
    If a logger of that name already exists, then it will be
147
    returned.  Otherwise, a new logger will be instantiated and
148
    then linked with its existing ancestors as well as children.
149
150
    @param name The name of the logger to retrieve.
151
152
    */
153
    LoggerPtr getLogger(const LogString& name) override;
154
155
    /**
156
    Retrieve the \c name Logger instance using
157
    <code>factory</code> to create it if required.
158
159
    If a logger of that name already exists, then it will be
160
    returned.  Otherwise, a new logger will be instantiated by the
161
    <code>factory</code> parameter and linked with its existing
162
    ancestors as well as children.
163
164
    @param name The name of the logger to retrieve.
165
    @param factory The factory that will make the new logger instance.
166
167
    */
168
    LoggerPtr getLogger(const LogString& name,
169
      const spi::LoggerFactoryPtr& factory) override;
170
171
    /**
172
    Returns all the currently defined loggers in this hierarchy as
173
    a LoggerList.
174
175
    <p>The root logger is <em>not</em> included in the returned
176
    LoggerList.  */
177
    LoggerList getCurrentLoggers() const override;
178
179
    /**
180
    Get the root of this hierarchy.
181
    */
182
    LoggerPtr getRootLogger() const override;
183
184
    /**
185
    This method will return <code>true</code> if this repository is
186
    disabled for <code>level</code> object passed as parameter and
187
    <code>false</code> otherwise. See also the
188
    {@link #setThreshold(const LevelPtr&) setThreshold} method.  */
189
    bool isDisabled(int level) const override;
190
191
    /**
192
    Reset all values contained in this hierarchy instance to their
193
    default.  This removes all appenders from all categories, sets
194
    the level of all non-root categories to <code>null</code>,
195
    sets their additivity flag to <code>true</code> and sets the level
196
    of the root logger to DEBUG.  Moreover,
197
    message disabling is set its default "off" value.
198
199
    <p>Existing categories are not removed. They are just reset.
200
201
    <p>This method should be used sparingly and with care as it will
202
    block all logging until it is completed.</p>
203
    */
204
    void resetConfiguration() override;
205
206
    /**
207
    Used by subclasses to add a renderer to the hierarchy passed as parameter.
208
    */
209
    /**
210
    Shutting down a hierarchy will <em>safely</em> close and remove
211
    all appenders in all categories including the root logger.
212
213
    <p>Some appenders such as {@link net::XMLSocketAppender XMLSocketAppender}
214
    and AsyncAppender need to be closed before the
215
    application exists. Otherwise, pending logging events might be
216
    lost.
217
218
    <p>The <code>shutdown</code> method is careful to close nested
219
    appenders before closing regular appenders. This is allows
220
    configurations where a regular appender is attached to a logger
221
    and again to a nested appender.
222
    */
223
    void shutdown() override;
224
225
226
    virtual bool isConfigured() override;
227
    virtual void setConfigured(bool configured) override;
228
229
    /**
230
    Refresh the threshold in children of parent
231
    */
232
    void updateChildren(const Logger* parent);
233
234
    void clearAppenders();
235
236
    void addAppender(AppenderPtr appender);
237
238
    /**
239
    Remove the \c name Logger from the hierarchy.
240
241
    Note: The \c name Logger must be retrieved from the hierarchy
242
    \b after any subsequent configuration file change
243
    for the newly loaded settings to be used.
244
245
    @param name The logger to remove.
246
    @param ifNotUsed If true and use_count() indicates there are other references, do not remove the Logger and return false.
247
    @returns true if \c name Logger was removed from the hierarchy.
248
    */
249
#if LOG4CXX_ABI_VERSION <= 15
250
    bool removeLogger(const LogString& name, bool ifNotUsed = true);
251
#else
252
    bool removeLogger(const LogString& name, bool ifNotUsed = true) override;
253
#endif
254
255
  private:
256
257
    /**
258
     * Set the threshold.  The mutex must already be locked.
259
     */
260
    void setThresholdInternal(const LevelPtr& l);
261
262
    /**
263
     * Internal shutdown.  The mutex must already be locked.
264
     */
265
    void shutdownInternal();
266
267
    /**
268
    This method loops through all the *potential* parents of
269
    \c logger using the logger name.
270
    For example, for a logger named "w.x.y.z",
271
    loop through "w.x.y", "w.x" and "w", but not "w.x.y.z".
272
    There 3 possible cases:
273
274
    1) No entry for the potential parent of "w.x.y.z" exists
275
276
    We create a ProvisionNode for this potential parent and insert
277
    "w.x.y.z" in that provision node.
278
279
    2) There entry is of type Logger for the potential parent.
280
281
    The entry is "w.x.y.z"'s nearest existing parent. We update "w.x.y.z"'s
282
    parent field with this entry. We also break from the loop
283
    because updating our parent's parent is our parent's
284
    responsibility.
285
286
    3) There entry is of type ProvisionNode for this potential parent.
287
288
    We add "w.x.y.z" to the list of children for this potential parent.
289
    */
290
    void updateParents(const LoggerPtr& logger, const LoggerPtr& root);
291
292
    /**
293
    We update the links for all the children that placed themselves
294
    in the provision node 'pn'. The \c logger argument is a
295
    newly created Logger, a potential parent of all the
296
    children in 'pn'
297
298
    We loop on all the children 'c' in 'pn':
299
300
    If the child 'c' has been already linked to a child of
301
    'cat' then there is no need to update 'c'.
302
303
    Otherwise, we set the \c logger parent to 'c's parent and set
304
    'c's parent field to \c logger.
305
    */
306
    void updateChildren(ProvisionNode& pn, const LoggerPtr& logger);
307
308
    Hierarchy(const Hierarchy&);
309
    Hierarchy& operator=(const Hierarchy&);
310
311
};
312
313
}  //namespace log4cxx
314
315
#endif //_LOG4CXX_HIERARCHY_H