Coverage Report

Created: 2026-03-19 06:57

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
#if LOG4CXX_ABI_VERSION <= 15
235
    /**
236
     * @deprecated This function is deprecated and will be removed in a future version.
237
    */
238
    [[ deprecated( "Storing appenders is longer supported" ) ]]
239
    void clearAppenders();
240
241
    /**
242
     * @deprecated This function is deprecated and will be removed in a future version.
243
    */
244
    [[ deprecated( "Storing appenders is longer supported" ) ]]
245
    void addAppender(AppenderPtr appender);
246
#endif
247
    /**
248
    Remove the \c name Logger from the hierarchy.
249
250
    Note: The \c name Logger must be retrieved from the hierarchy
251
    \b after any subsequent configuration file change
252
    for the newly loaded settings to be used.
253
254
    @param name The logger to remove.
255
    @param ifNotUsed If true and use_count() indicates there are other references, do not remove the Logger and return false.
256
    @returns true if \c name Logger was removed from the hierarchy.
257
    */
258
#if LOG4CXX_ABI_VERSION <= 15
259
    bool removeLogger(const LogString& name, bool ifNotUsed = true);
260
#else
261
    bool removeLogger(const LogString& name, bool ifNotUsed = true) override;
262
#endif
263
264
  private:
265
266
    /**
267
     * Set the threshold.  The mutex must already be locked.
268
     */
269
    void setThresholdInternal(const LevelPtr& l);
270
271
    /**
272
     * Internal shutdown.  The mutex must already be locked.
273
     */
274
    void shutdownInternal();
275
276
    /**
277
    This method loops through all the *potential* parents of
278
    \c logger using the logger name.
279
    For example, for a logger named "w.x.y.z",
280
    loop through "w.x.y", "w.x" and "w", but not "w.x.y.z".
281
    There 3 possible cases:
282
283
    1) No entry for the potential parent of "w.x.y.z" exists
284
285
    We create a ProvisionNode for this potential parent and insert
286
    "w.x.y.z" in that provision node.
287
288
    2) There entry is of type Logger for the potential parent.
289
290
    The entry is "w.x.y.z"'s nearest existing parent. We update "w.x.y.z"'s
291
    parent field with this entry. We also break from the loop
292
    because updating our parent's parent is our parent's
293
    responsibility.
294
295
    3) There entry is of type ProvisionNode for this potential parent.
296
297
    We add "w.x.y.z" to the list of children for this potential parent.
298
    */
299
    void updateParents(const LoggerPtr& logger, const LoggerPtr& root);
300
301
    /**
302
    We update the links for all the children that placed themselves
303
    in the provision node 'pn'. The \c logger argument is a
304
    newly created Logger, a potential parent of all the
305
    children in 'pn'
306
307
    We loop on all the children 'c' in 'pn':
308
309
    If the child 'c' has been already linked to a child of
310
    'cat' then there is no need to update 'c'.
311
312
    Otherwise, we set the \c logger parent to 'c's parent and set
313
    'c's parent field to \c logger.
314
    */
315
    void updateChildren(ProvisionNode& pn, const LoggerPtr& logger);
316
317
    Hierarchy(const Hierarchy&);
318
    Hierarchy& operator=(const Hierarchy&);
319
320
};
321
322
}  //namespace log4cxx
323
324
#endif //_LOG4CXX_HIERARCHY_H