Coverage Report

Created: 2025-07-11 07:00

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