Coverage Report

Created: 2026-05-30 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/logging-log4cxx/src/main/cpp/propertyconfigurator.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/propertyconfigurator.h>
20
#include <log4cxx/asyncappender.h>
21
#include <log4cxx/helpers/properties.h>
22
#include <log4cxx/helpers/loglog.h>
23
#include <log4cxx/helpers/exception.h>
24
#include <log4cxx/logmanager.h>
25
#include <log4cxx/helpers/optionconverter.h>
26
#include <log4cxx/level.h>
27
#if LOG4CXX_ABI_VERSION <= 15
28
#include <log4cxx/defaultloggerfactory.h>
29
#else
30
#include <log4cxx/spi/loggerfactory.h>
31
#endif
32
#include <log4cxx/helpers/stringhelper.h>
33
#include <log4cxx/layout.h>
34
#include <log4cxx/config/propertysetter.h>
35
#include <log4cxx/helpers/stringtokenizer.h>
36
#include <log4cxx/helpers/transcoder.h>
37
#include <log4cxx/helpers/fileinputstream.h>
38
#include <log4cxx/helpers/loader.h>
39
#include <log4cxx/helpers/threadutility.h>
40
#include <log4cxx/helpers/singletonholder.h>
41
#include <log4cxx/rolling/rollingfileappender.h>
42
43
#define LOG4CXX 1
44
#include <log4cxx/helpers/aprinitializer.h>
45
46
using namespace LOG4CXX_NS;
47
using namespace LOG4CXX_NS::spi;
48
using namespace LOG4CXX_NS::helpers;
49
using namespace LOG4CXX_NS::config;
50
using namespace LOG4CXX_NS::rolling;
51
52
#include <log4cxx/helpers/filewatchdog.h>
53
namespace LOG4CXX_NS
54
{
55
class PropertyWatchdog  : public FileWatchdog
56
{
57
  public:
58
0
    PropertyWatchdog(const File& filename) : FileWatchdog(filename)
59
0
    {
60
0
    }
61
62
    /**
63
    Call PropertyConfigurator#doConfigure(const String& configFileName,
64
    const spi::LoggerRepositoryPtr& hierarchy) with the
65
    <code>filename</code> to reconfigure log4cxx.
66
    */
67
    void doOnChange()
68
0
    {
69
0
      PropertyConfigurator().doConfigure(file(),
70
0
        LogManager::getLoggerRepository());
71
0
    }
72
73
    static void startWatching(const File& filename, long delay)
74
0
    {
75
0
      using WatchdogHolder = SingletonHolder<PropertyWatchdog>;
76
0
      auto pHolder = APRInitializer::getOrAddUnique<WatchdogHolder>
77
0
        ( [&filename]() -> ObjectPtr
78
0
          { return std::make_shared<WatchdogHolder>(filename); }
79
0
        );
80
0
      auto& pdog = pHolder->value();
81
0
      pdog.setFile(filename);
82
0
      pdog.setDelay(0 < delay ? delay : FileWatchdog::DEFAULT_DELAY);
83
0
      pdog.start();
84
0
    }
85
};
86
}
87
88
IMPLEMENT_LOG4CXX_OBJECT(PropertyConfigurator)
89
90
using RegistryType = std::map<LogString, AppenderPtr>;
91
using RegistryPtr = std::unique_ptr<RegistryType>;
92
93
#if 15 < LOG4CXX_ABI_VERSION
94
struct PropertyConfigurator::PrivateData
95
{
96
97
  /**
98
  Used internally to keep track of configured appenders.
99
  */
100
  RegistryPtr registry{ std::make_unique<RegistryType>() };
101
102
  /**
103
  Used to create new instances of logger
104
  */
105
  spi::LoggerFactoryPtr loggerFactory{ std::make_shared<LoggerFactory>() };
106
107
  /**
108
  True if an appender was added to a logger
109
  */
110
  bool appenderAdded{ false };
111
};
112
PropertyConfigurator::PropertyConfigurator()
113
  : m_priv{ std::make_unique<PrivateData>() }
114
#else
115
0
#define m_priv this
116
PropertyConfigurator::PropertyConfigurator()
117
0
  : registry(new std::map<LogString, AppenderPtr>())
118
0
  , loggerFactory(new DefaultLoggerFactory())
119
#endif
120
0
{
121
0
}
Unexecuted instantiation: log4cxx::PropertyConfigurator::PropertyConfigurator()
Unexecuted instantiation: log4cxx::PropertyConfigurator::PropertyConfigurator()
122
123
PropertyConfigurator::~PropertyConfigurator()
124
0
{
125
0
#if LOG4CXX_ABI_VERSION <= 15
126
0
  delete registry;
127
0
#endif
128
0
}
129
130
spi::ConfigurationStatus PropertyConfigurator::doConfigure
131
  ( const File&                     configFileName
132
#if LOG4CXX_ABI_VERSION <= 15
133
  , spi::LoggerRepositoryPtr        repository
134
#else
135
  , const spi::LoggerRepositoryPtr& repository
136
#endif
137
  )
138
0
{
139
0
  auto result = spi::ConfigurationStatus::NotConfigured;
140
0
  if (LogLog::isDebugEnabled())
141
0
  {
142
0
    LogLog::debug(LOG4CXX_STR("Loading configuration file [")
143
0
      + configFileName.getPath() + LOG4CXX_STR("]"));
144
0
  }
145
0
  Properties props = Configurator::properties();
146
0
  try
147
0
  {
148
0
    InputStreamPtr inputStream = InputStreamPtr( new FileInputStream(configFileName) );
149
0
    props.load(inputStream);
150
0
  }
151
0
  catch (const IOException& ex)
152
0
  {
153
0
    LogLog::error(LOG4CXX_STR("Could not load properties from [")
154
0
      + configFileName.getPath() + LOG4CXX_STR("]"), ex);
155
0
    return result;
156
0
  }
157
158
0
  try
159
0
  {
160
0
    result = doConfigure(props, repository ? repository : LogManager::getLoggerRepository());
161
0
#if LOG4CXX_ABI_VERSION <= 15
162
0
    if (m_priv->registry->empty())
163
#else
164
    if (!m_priv->appenderAdded)
165
#endif
166
0
    {
167
0
      LogLog::warn(LOG4CXX_STR("[") + configFileName.getPath()
168
0
        + LOG4CXX_STR("] did not add an ") + Appender::getStaticClass().getName()
169
0
        + LOG4CXX_STR(" to a logger"));
170
0
    }
171
0
  }
172
0
  catch (const std::exception& ex)
173
0
  {
174
0
    LogLog::error(LOG4CXX_STR("Exception thrown processing [")
175
0
      + configFileName.getPath() + LOG4CXX_STR("]: "), ex);
176
0
  }
177
178
0
  return result;
179
0
}
180
181
spi::ConfigurationStatus PropertyConfigurator::configure(const File& configFilename)
182
0
{
183
0
  return PropertyConfigurator().doConfigure(configFilename, LogManager::getLoggerRepository());
184
0
}
185
186
spi::ConfigurationStatus PropertyConfigurator::configure(helpers::Properties& properties)
187
0
{
188
0
  return PropertyConfigurator().doConfigure(properties, LogManager::getLoggerRepository());
189
0
}
190
191
#if LOG4CXX_ABI_VERSION <= 15
192
spi::ConfigurationStatus PropertyConfigurator::configureAndWatch(const File& configFilename)
193
0
{
194
0
  return configureAndWatch(configFilename, FileWatchdog::DEFAULT_DELAY);
195
0
}
196
#endif
197
198
spi::ConfigurationStatus PropertyConfigurator::configureAndWatch(
199
  const File& configFilename, long delay)
200
0
{
201
0
  spi::ConfigurationStatus stat = PropertyConfigurator().doConfigure(configFilename, LogManager::getLoggerRepository());
202
0
  PropertyWatchdog::startWatching(configFilename, delay);
203
0
  return stat;
204
0
}
205
206
spi::ConfigurationStatus PropertyConfigurator::doConfigure(helpers::Properties& properties,
207
  spi::LoggerRepositoryPtr hierarchy)
208
0
{
209
0
  LogString debugValue(properties.getProperty(LOG4CXX_STR("log4j.debug")));
210
0
  if (!debugValue.empty())
211
0
  {
212
0
    LogLog::setInternalDebugging(OptionConverter::toBoolean(debugValue, true));
213
0
  }
214
215
0
  LogString colorValue(properties.getProperty(LOG4CXX_STR("log4j.color")));
216
0
  if (!colorValue.empty())
217
0
  {
218
0
    LogLog::setColorEnabled(OptionConverter::toBoolean(colorValue, true));
219
0
  }
220
221
0
  LogString thresholdStr =
222
0
    OptionConverter::findAndSubst(LOG4CXX_STR("log4j.threshold"), properties);
223
224
0
  if (!thresholdStr.empty())
225
0
  {
226
0
    hierarchy->setThreshold(OptionConverter::toLevel(thresholdStr, Level::getAll()));
227
0
    if (LogLog::isDebugEnabled())
228
0
    {
229
0
      LogLog::debug(LOG4CXX_STR("Repository threshold =[")
230
0
        + hierarchy->getThreshold()->toString()
231
0
        + LOG4CXX_STR("]"));
232
0
    }
233
0
  }
234
235
0
  LogString threadConfigurationValue(properties.getProperty(LOG4CXX_STR("log4j.threadConfiguration")));
236
237
0
  if ( threadConfigurationValue == LOG4CXX_STR("NoConfiguration") )
238
0
  {
239
0
    helpers::ThreadUtility::configure( ThreadConfigurationType::NoConfiguration );
240
0
  }
241
0
  else if ( threadConfigurationValue == LOG4CXX_STR("BlockSignalsOnly") )
242
0
  {
243
0
    helpers::ThreadUtility::configure( ThreadConfigurationType::BlockSignalsOnly );
244
0
  }
245
0
  else if ( threadConfigurationValue == LOG4CXX_STR("NameThreadOnly") )
246
0
  {
247
0
    helpers::ThreadUtility::configure( ThreadConfigurationType::NameThreadOnly );
248
0
  }
249
0
  else if ( threadConfigurationValue == LOG4CXX_STR("BlockSignalsAndNameThread") )
250
0
  {
251
0
    helpers::ThreadUtility::configure( ThreadConfigurationType::BlockSignalsAndNameThread );
252
0
  }
253
254
0
  configureRootLogger(properties, hierarchy);
255
0
  configureLoggerFactory(properties);
256
0
  parseCatsAndRenderers(properties, hierarchy);
257
0
  LogLog::debug(LOG4CXX_STR("Finished configuring."));
258
0
#if LOG4CXX_ABI_VERSION <= 15
259
0
  auto result = m_priv->registry->empty()
260
#else
261
  auto result = !m_priv->appenderAdded
262
#endif
263
0
    ? spi::ConfigurationStatus::NotConfigured
264
0
    : spi::ConfigurationStatus::Configured;
265
266
0
  if (spi::ConfigurationStatus::Configured == result)
267
0
    hierarchy->setConfigured(true);
268
0
  return result;
269
0
}
270
271
void PropertyConfigurator::configureLoggerFactory(helpers::Properties& props)
272
0
{
273
0
  LogString factoryClassName =
274
0
    OptionConverter::findAndSubst(LOG4CXX_STR("log4j.loggerFactory"), props);
275
276
0
  if (!factoryClassName.empty())
277
0
  {
278
0
    auto instance = OptionConverter::instantiateByClassName
279
0
      ( StringHelper::trim(factoryClassName)
280
0
      , LoggerFactory::getStaticClass()
281
0
#if LOG4CXX_ABI_VERSION <= 15
282
0
      , std::make_shared<DefaultLoggerFactory>()
283
#else
284
      , std::make_shared<LoggerFactory>()
285
#endif
286
0
      );
287
288
0
    m_priv->loggerFactory = LOG4CXX_NS::cast<LoggerFactory>( instance );
289
0
    PropertySetter::setProperties(m_priv->loggerFactory, props, LOG4CXX_STR("log4j.factory."));
290
0
  }
291
0
}
292
293
void PropertyConfigurator::configureRootLogger(helpers::Properties& props,
294
  spi::LoggerRepositoryPtr& hierarchy)
295
0
{
296
0
  LogString effectivePrefix(LOG4CXX_STR("log4j.rootLogger"));
297
0
  LogString value = OptionConverter::findAndSubst(effectivePrefix, props);
298
299
0
  if (value.empty())
300
0
  {
301
0
    effectivePrefix = LOG4CXX_STR("log4j.rootCategory");
302
0
    value = OptionConverter::findAndSubst(effectivePrefix, props);
303
0
  }
304
305
0
  if (value.empty())
306
0
  {
307
0
    LogLog::debug(LOG4CXX_STR("Neither 'log4j.rootLogger' or 'log4j.rootCategory' found. Is this OK?"));
308
0
  }
309
0
  else
310
0
  {
311
0
    LoggerPtr root = hierarchy->getRootLogger();
312
0
    parseLogger(props, root, effectivePrefix, LOG4CXX_STR("root"), value, true);
313
0
  }
314
0
}
315
316
void PropertyConfigurator::parseCatsAndRenderers(helpers::Properties& props,
317
  spi::LoggerRepositoryPtr& hierarchy)
318
0
{
319
0
  for (auto key : props.propertyNames())
320
0
  {
321
0
    auto categoryFound = (0 == key.find(LOG4CXX_STR("log4j.category.")));
322
0
    if (categoryFound || 0 == key.find(LOG4CXX_STR("log4j.logger.")))
323
0
    {
324
0
      auto prefixLength =
325
0
        ( categoryFound
326
0
        ? LogString(LOG4CXX_STR("log4j.category."))
327
0
        : LogString(LOG4CXX_STR("log4j.logger."))
328
0
        ).length();
329
0
      auto loggerName = key.substr(prefixLength);
330
0
      auto value = OptionConverter::findAndSubst(key, props);
331
0
      auto logger = hierarchy->getLogger(loggerName, m_priv->loggerFactory);
332
0
      auto additivity = parseAdditivityForLogger(props, logger, loggerName);
333
0
      parseLogger(props, logger, key, loggerName, value, additivity);
334
335
0
    }
336
0
  }
337
0
}
338
339
bool PropertyConfigurator::parseAdditivityForLogger(helpers::Properties& props,
340
  LoggerPtr& cat, const LogString& loggerName)
341
0
{
342
0
  LogString value(OptionConverter::findAndSubst(LOG4CXX_STR("log4j.additivity.") + loggerName, props));
343
  // touch additivity only if necessary
344
0
  if (!value.empty())
345
0
  {
346
0
    bool additivity = OptionConverter::toBoolean(value, true);
347
0
    if (LogLog::isDebugEnabled())
348
0
    {
349
0
      LogLog::debug(LOG4CXX_STR("Setting [") + loggerName + LOG4CXX_STR("] additivity to [")
350
0
        + (additivity ? LogString(LOG4CXX_STR("true")) : LogString(LOG4CXX_STR("false")) + LOG4CXX_STR("]")));
351
0
    }
352
353
0
    return additivity;
354
0
  }
355
356
0
  return true;
357
0
}
358
359
/**
360
        This method must work for the root logger as well.
361
*/
362
void PropertyConfigurator::parseLogger(
363
  helpers::Properties& props, LoggerPtr& logger, const LogString& /* optionKey */,
364
  const LogString& loggerName, const LogString& value, bool additivity)
365
0
{
366
0
  if (LogLog::isDebugEnabled())
367
0
  {
368
0
    LogLog::debug(((LogString) LOG4CXX_STR("Parsing for ["))
369
0
      + loggerName
370
0
      + LOG4CXX_STR("] with value=[")
371
0
      + value + LOG4CXX_STR("]"));
372
0
  }
373
374
  // We must skip over ',' but not white space
375
0
  StringTokenizer st(value, LOG4CXX_STR(","));
376
377
  // If value is not in the form ", appender.." or "", then we should set
378
  // the level of the logger.
379
0
  if (!(value.find(LOG4CXX_STR(",")) == 0 || value.empty()))
380
0
  {
381
    // just to be on the safe side...
382
0
    if (!st.hasMoreTokens())
383
0
    {
384
0
      return;
385
0
    }
386
387
0
    LogString levelStr = st.nextToken();
388
389
    // If the level value is inherited, set logger level value to
390
    // null. We also check that the user has not specified inherited for the
391
    // root logger.
392
0
    if (StringHelper::equalsIgnoreCase(levelStr, LOG4CXX_STR("INHERITED"), LOG4CXX_STR("inherited"))
393
0
      || StringHelper::equalsIgnoreCase(levelStr, LOG4CXX_STR("NULL"), LOG4CXX_STR("null")))
394
0
    {
395
0
      if (loggerName == LOG4CXX_STR("root"))
396
0
      {
397
0
        LogLog::warn(LOG4CXX_STR("Root level cannot be ") + levelStr + LOG4CXX_STR(". Ignoring directive."));
398
0
      }
399
0
      else
400
0
      {
401
0
        logger->setLevel(0);
402
0
      }
403
0
    }
404
0
    else
405
0
    {
406
0
      logger->setLevel(OptionConverter::toLevel(levelStr, Level::getDebug()));
407
0
    }
408
0
    if (LogLog::isDebugEnabled())
409
0
    {
410
0
      LogLog::debug(loggerName + LOG4CXX_STR(" level set to ") +
411
0
        logger->getEffectiveLevel()->toString());
412
0
    }
413
414
0
  }
415
416
0
  AsyncAppenderPtr async;
417
0
  auto lsAsynchronous = OptionConverter::findAndSubst(LOG4CXX_STR("log4j.asynchronous.") + loggerName, props);
418
0
  if (!lsAsynchronous.empty() && OptionConverter::toBoolean(lsAsynchronous, true))
419
0
  {
420
0
    async = std::make_shared<AsyncAppender>();
421
0
    async->setName(loggerName);
422
0
  }
423
424
0
  std::vector<AppenderPtr> newappenders;
425
0
  while (st.hasMoreTokens())
426
0
  {
427
0
    auto appenderName = StringHelper::trim(st.nextToken());
428
429
0
    if (appenderName.empty() || appenderName == LOG4CXX_STR(","))
430
0
    {
431
0
      continue;
432
0
    }
433
434
0
    if (LogLog::isDebugEnabled())
435
0
    {
436
0
      LogLog::debug(LOG4CXX_STR("Parsing ") + Appender::getStaticClass().getName()
437
0
        + LOG4CXX_STR(" named [") + appenderName + LOG4CXX_STR("]"));
438
0
    }
439
0
    if (auto appender = parseAppender(props, appenderName))
440
0
    {
441
0
      newappenders.push_back(appender);
442
0
      if (log4cxx::cast<AsyncAppender>(appender)) // An explicitly configured AsyncAppender?
443
0
        async.reset(); // Not required
444
0
      if (async)
445
0
        async->addAppender(appender);
446
0
    }
447
0
  }
448
#if 15 < LOG4CXX_ABI_VERSION
449
  if (!newappenders.empty())
450
    m_priv->appenderAdded = true;
451
#endif
452
0
  if (async && !newappenders.empty())
453
0
  {
454
0
    if (LogLog::isDebugEnabled())
455
0
    {
456
0
      LogLog::debug(LOG4CXX_STR("Asynchronous logging for [")
457
0
          + loggerName + LOG4CXX_STR("] is on"));
458
0
    }
459
0
    logger->reconfigure( {async}, additivity );
460
0
  }
461
0
  else
462
0
    logger->reconfigure( newappenders, additivity );
463
0
}
464
465
AppenderPtr PropertyConfigurator::parseAppender(
466
  helpers::Properties& props, const LogString& appenderName)
467
0
{
468
0
  AppenderPtr appender = registryGet(appenderName);
469
470
0
  if (appender != 0)
471
0
  {
472
0
    if (LogLog::isDebugEnabled())
473
0
    {
474
0
      LogLog::debug((LogString) LOG4CXX_STR("Appender [")
475
0
        + appenderName + LOG4CXX_STR("] was already parsed."));
476
0
    }
477
478
0
    return appender;
479
0
  }
480
481
  // Appender was not previously initialized.
482
0
  LogString prefix = LOG4CXX_STR("log4j.appender.") + appenderName;
483
0
  LogString layoutPrefix = prefix + LOG4CXX_STR(".layout");
484
485
0
  std::shared_ptr<Object> obj =
486
0
    OptionConverter::instantiateByKey(
487
0
      props, prefix, Appender::getStaticClass(), 0);
488
0
  appender = LOG4CXX_NS::cast<Appender>( obj );
489
490
  // Map obsolete DailyRollingFileAppender property configuration
491
0
  if (!appender &&
492
0
    StringHelper::endsWith(OptionConverter::findAndSubst(prefix, props), LOG4CXX_STR("DailyRollingFileAppender")))
493
0
  {
494
0
    appender = std::make_shared<RollingFileAppender>();
495
0
    auto datePattern = OptionConverter::findAndSubst(prefix + LOG4CXX_STR(".datePattern"), props);
496
0
    if (!datePattern.empty())
497
0
      props.put(prefix + LOG4CXX_STR(".fileDatePattern"), datePattern);
498
0
  }
499
500
0
  if (!appender)
501
0
  {
502
0
    LogLog::error((LogString) LOG4CXX_STR("Could not instantiate ") + Appender::getStaticClass().getName()
503
0
      + LOG4CXX_STR(" named [") + appenderName + LOG4CXX_STR("]"));
504
0
    return 0;
505
0
  }
506
507
0
  appender->setName(appenderName);
508
509
0
  if (appender->instanceof(OptionHandler::getStaticClass()))
510
0
  {
511
0
    if (appender->requiresLayout())
512
0
    {
513
0
      LayoutPtr layout;
514
0
      std::shared_ptr<Object> obj =
515
0
        OptionConverter::instantiateByKey(
516
0
          props, layoutPrefix, Layout::getStaticClass(), 0);
517
0
      layout = LOG4CXX_NS::cast<Layout>( obj );
518
519
0
      if (layout != 0)
520
0
      {
521
0
        appender->setLayout(layout);
522
0
        if (LogLog::isDebugEnabled())
523
0
        {
524
0
          LogLog::debug((LogString) LOG4CXX_STR("Parsing ") + Layout::getStaticClass().getName()
525
0
            + LOG4CXX_STR(" options for [") + appenderName + LOG4CXX_STR("]"));
526
0
        }
527
528
0
        PropertySetter::setProperties(layout, props, layoutPrefix + LOG4CXX_STR("."));
529
0
        if (LogLog::isDebugEnabled())
530
0
        {
531
0
          LogLog::debug((LogString) LOG4CXX_STR("End of parsing for [")
532
0
            + appenderName +  LOG4CXX_STR("]"));
533
0
        }
534
0
      }
535
0
    }
536
537
0
    RollingFileAppenderPtr rolling = LOG4CXX_NS::cast<rolling::RollingFileAppender>(appender);
538
0
    if (rolling)
539
0
    {
540
0
      LogString rollingPolicyKey = prefix + LOG4CXX_STR(".rollingPolicy");
541
0
      if (!OptionConverter::findAndSubst(rollingPolicyKey, props).empty())
542
0
      {
543
0
        RollingPolicyPtr rollingPolicy;
544
0
        std::shared_ptr<Object> rolling_obj =
545
0
          OptionConverter::instantiateByKey(
546
0
            props, rollingPolicyKey, RollingPolicy::getStaticClass(), 0);
547
0
        rollingPolicy = LOG4CXX_NS::cast<RollingPolicy>( rolling_obj );
548
0
        if(rollingPolicy)
549
0
        {
550
0
          rolling->setRollingPolicy(rollingPolicy);
551
552
0
          if (LogLog::isDebugEnabled())
553
0
          {
554
0
            LogLog::debug((LogString) LOG4CXX_STR("Parsing ") + RollingPolicy::getStaticClass().getName()
555
0
              + LOG4CXX_STR(" options for [") + appenderName + LOG4CXX_STR("]"));
556
0
          }
557
0
          PropertySetter::setProperties(rollingPolicy, props, rollingPolicyKey + LOG4CXX_STR("."));
558
0
        }
559
0
      }
560
561
0
      LogString triggeringPolicyKey = prefix + LOG4CXX_STR(".triggeringPolicy");
562
0
      if (!OptionConverter::findAndSubst(triggeringPolicyKey, props).empty())
563
0
      {
564
0
        TriggeringPolicyPtr triggeringPolicy;
565
0
        std::shared_ptr<Object> triggering_obj =
566
0
          OptionConverter::instantiateByKey(
567
0
            props, triggeringPolicyKey, TriggeringPolicy::getStaticClass(), 0);
568
0
        triggeringPolicy = LOG4CXX_NS::cast<TriggeringPolicy>( triggering_obj );
569
0
        if(triggeringPolicy)
570
0
        {
571
0
          rolling->setTriggeringPolicy(triggeringPolicy);
572
573
0
          if (LogLog::isDebugEnabled())
574
0
          {
575
0
            LogLog::debug((LogString) LOG4CXX_STR("Parsing ") + TriggeringPolicy::getStaticClass().getName()
576
0
              + LOG4CXX_STR(" options for [") + appenderName + LOG4CXX_STR("]"));
577
0
          }
578
0
          PropertySetter::setProperties(triggeringPolicy, props, triggeringPolicyKey + LOG4CXX_STR("."));
579
0
        }
580
0
      }
581
0
    }
582
583
0
    PropertySetter::setProperties(appender, props, prefix + LOG4CXX_STR("."));
584
0
    if (LogLog::isDebugEnabled())
585
0
    {
586
0
      LogLog::debug((LogString) LOG4CXX_STR("Parsed [")
587
0
        + appenderName + LOG4CXX_STR("] options."));
588
0
    }
589
0
  }
590
591
0
  registryPut(appender);
592
593
0
  return appender;
594
0
}
595
596
void PropertyConfigurator::registryPut(const AppenderPtr& appender)
597
0
{
598
0
  (*m_priv->registry)[appender->getName()] = appender;
599
0
}
600
601
AppenderPtr PropertyConfigurator::registryGet(const LogString& name)
602
0
{
603
0
  auto it = m_priv->registry->find(name);
604
0
  return (it == m_priv->registry->end()) ? AppenderPtr() : it->second;
605
0
}