/src/logging-log4cxx/src/main/cpp/optionconverter.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/spi/loggerfactory.h> | 
| 20 |  | #include <log4cxx/spi/loggerrepository.h> | 
| 21 |  | #include <log4cxx/appenderskeleton.h> | 
| 22 |  | #include <log4cxx/helpers/optionconverter.h> | 
| 23 |  | #include <algorithm> | 
| 24 |  | #include <ctype.h> | 
| 25 |  | #include <log4cxx/helpers/stringhelper.h> | 
| 26 |  | #include <log4cxx/helpers/exception.h> | 
| 27 |  | #include <stdlib.h> | 
| 28 |  | #include <log4cxx/helpers/properties.h> | 
| 29 |  | #include <log4cxx/helpers/loglog.h> | 
| 30 |  | #include <log4cxx/level.h> | 
| 31 |  | #include <log4cxx/helpers/object.h> | 
| 32 |  | #include <log4cxx/helpers/class.h> | 
| 33 |  | #include <log4cxx/helpers/loader.h> | 
| 34 |  | #include <log4cxx/helpers/system.h> | 
| 35 |  | #include <log4cxx/propertyconfigurator.h> | 
| 36 |  | #include <log4cxx/helpers/transcoder.h> | 
| 37 |  | #include <log4cxx/file.h> | 
| 38 |  | #include <log4cxx/xml/domconfigurator.h> | 
| 39 |  | #include <log4cxx/logmanager.h> | 
| 40 |  | #if !defined(LOG4CXX) | 
| 41 |  |   #define LOG4CXX 1 | 
| 42 |  | #endif | 
| 43 |  | #include <log4cxx/helpers/aprinitializer.h> | 
| 44 |  | #include <log4cxx/helpers/filewatchdog.h> | 
| 45 |  | #include <log4cxx/helpers/singletonholder.h> | 
| 46 |  |  | 
| 47 |  | namespace LOG4CXX_NS | 
| 48 |  | { | 
| 49 |  |  | 
| 50 |  | class ConfiguratorWatchdog  : public helpers::FileWatchdog | 
| 51 |  | { | 
| 52 |  |   spi::ConfiguratorPtr m_config; | 
| 53 |  |   public: | 
| 54 |  |     ConfiguratorWatchdog(const spi::ConfiguratorPtr& config, const File& filename) | 
| 55 | 0 |         : helpers::FileWatchdog(filename) | 
| 56 | 0 |         , m_config(config) | 
| 57 | 0 |     { | 
| 58 | 0 |     } | 
| 59 |  |  | 
| 60 |  |     /** | 
| 61 |  |     Call PropertyConfigurator#doConfigure(const String& configFileName, | 
| 62 |  |     const spi::LoggerRepositoryPtr& hierarchy) with the | 
| 63 |  |     <code>filename</code> to reconfigure log4cxx. | 
| 64 |  |     */ | 
| 65 |  |     void doOnChange() override | 
| 66 | 0 |     { | 
| 67 | 0 |         m_config->doConfigure(file(), LogManager::getLoggerRepository()); | 
| 68 | 0 |     } | 
| 69 |  |  | 
| 70 |  |   static void startWatching(const spi::ConfiguratorPtr& config, const File& filename, long delay) | 
| 71 | 0 |   { | 
| 72 | 0 |     using WatchdogHolder = helpers::SingletonHolder<ConfiguratorWatchdog>; | 
| 73 | 0 |     auto pHolder = helpers::APRInitializer::getOrAddUnique<WatchdogHolder> | 
| 74 | 0 |       ( [&config, &filename]() -> helpers::ObjectPtr | 
| 75 | 0 |         { return std::make_shared<WatchdogHolder>(config, filename); } | 
| 76 | 0 |       ); | 
| 77 | 0 |     auto& dog = pHolder->value(); | 
| 78 | 0 |     dog.m_config = config; | 
| 79 | 0 |     dog.setFile(filename); | 
| 80 | 0 |     dog.setDelay(delay); | 
| 81 | 0 |     dog.start(); | 
| 82 | 0 |   } | 
| 83 |  | }; | 
| 84 |  |  | 
| 85 |  | } | 
| 86 |  |  | 
| 87 |  | using namespace LOG4CXX_NS; | 
| 88 |  | using namespace LOG4CXX_NS::helpers; | 
| 89 |  | using namespace LOG4CXX_NS::spi; | 
| 90 |  |  | 
| 91 |  |  | 
| 92 |  | LogString OptionConverter::convertSpecialChars(const LogString& s) | 
| 93 | 0 | { | 
| 94 | 0 |   logchar c; | 
| 95 | 0 |   LogString sbuf; | 
| 96 |  | 
 | 
| 97 | 0 |   LogString::const_iterator i = s.begin(); | 
| 98 |  | 
 | 
| 99 | 0 |   while (i != s.end()) | 
| 100 | 0 |   { | 
| 101 | 0 |     c = *i++; | 
| 102 |  | 
 | 
| 103 | 0 |     if (i != s.end() && c == 0x5C /* '\\' */) | 
| 104 | 0 |     { | 
| 105 | 0 |       c =  *i++; | 
| 106 |  | 
 | 
| 107 | 0 |       switch (c) | 
| 108 | 0 |       { | 
| 109 | 0 |         case 0x6E: //'n' | 
| 110 | 0 |           c = 0x0A; | 
| 111 | 0 |           break; | 
| 112 |  |  | 
| 113 | 0 |         case 0x72: //'r' | 
| 114 | 0 |           c = 0x0D; | 
| 115 | 0 |           break; | 
| 116 |  |  | 
| 117 | 0 |         case 0x74: //'t' | 
| 118 | 0 |           c = 0x09; | 
| 119 | 0 |           break; | 
| 120 |  |  | 
| 121 | 0 |         case 0x66: //'f' | 
| 122 | 0 |           c = 0x0C; | 
| 123 | 0 |           break; | 
| 124 |  |  | 
| 125 | 0 |         default: | 
| 126 | 0 |           break; | 
| 127 | 0 |       } | 
| 128 | 0 |     } | 
| 129 |  |  | 
| 130 | 0 |     sbuf.append(1, c); | 
| 131 | 0 |   } | 
| 132 |  |  | 
| 133 | 0 |   return sbuf; | 
| 134 | 0 | } | 
| 135 |  |  | 
| 136 |  |  | 
| 137 |  | bool OptionConverter::toBoolean(const LogString& value, bool dEfault) | 
| 138 | 2 | { | 
| 139 | 2 |   if (value.length() >= 4) | 
| 140 | 2 |   { | 
| 141 | 2 |     if (StringHelper::equalsIgnoreCase(value.substr(0, 4), | 
| 142 | 2 |         LOG4CXX_STR("TRUE"), LOG4CXX_STR("true"))) | 
| 143 | 1 |     { | 
| 144 | 1 |       return true; | 
| 145 | 1 |     } | 
| 146 | 2 |   } | 
| 147 |  |  | 
| 148 | 1 |   if (dEfault && value.length() >= 5) | 
| 149 | 0 |   { | 
| 150 | 0 |     if (StringHelper::equalsIgnoreCase(value.substr(0, 5), | 
| 151 | 0 |         LOG4CXX_STR("FALSE"), LOG4CXX_STR("false"))) | 
| 152 | 0 |     { | 
| 153 | 0 |       return false; | 
| 154 | 0 |     } | 
| 155 | 0 |   } | 
| 156 |  |  | 
| 157 | 1 |   return dEfault; | 
| 158 | 1 | } | 
| 159 |  |  | 
| 160 |  | int OptionConverter::toInt(const LogString& value, int dEfault) | 
| 161 | 0 | { | 
| 162 | 0 |   LogString trimmed(StringHelper::trim(value)); | 
| 163 |  | 
 | 
| 164 | 0 |   if (trimmed.empty()) | 
| 165 | 0 |   { | 
| 166 | 0 |     return dEfault; | 
| 167 | 0 |   } | 
| 168 |  |  | 
| 169 | 0 |   LOG4CXX_ENCODE_CHAR(cvalue, trimmed); | 
| 170 |  | 
 | 
| 171 | 0 |   return (int) atol(cvalue.c_str()); | 
| 172 | 0 | } | 
| 173 |  |  | 
| 174 |  | long OptionConverter::toFileSize(const LogString& s, long dEfault) | 
| 175 | 0 | { | 
| 176 | 0 |   if (s.empty()) | 
| 177 | 0 |   { | 
| 178 | 0 |     return dEfault; | 
| 179 | 0 |   } | 
| 180 |  |  | 
| 181 | 0 |   size_t index = s.find_first_of(LOG4CXX_STR("bB")); | 
| 182 |  | 
 | 
| 183 | 0 |   if (index != LogString::npos && index > 0) | 
| 184 | 0 |   { | 
| 185 | 0 |     long multiplier = 1; | 
| 186 | 0 |     index--; | 
| 187 |  | 
 | 
| 188 | 0 |     if (s[index] == 0x6B /* 'k' */ || s[index] == 0x4B /* 'K' */) | 
| 189 | 0 |     { | 
| 190 | 0 |       multiplier = 1024; | 
| 191 | 0 |     } | 
| 192 | 0 |     else if (s[index] == 0x6D /* 'm' */ || s[index] == 0x4D /* 'M' */) | 
| 193 | 0 |     { | 
| 194 | 0 |       multiplier = 1024 * 1024; | 
| 195 | 0 |     } | 
| 196 | 0 |     else if (s[index] == 0x67 /* 'g'*/ || s[index] == 0x47 /* 'G' */) | 
| 197 | 0 |     { | 
| 198 | 0 |       multiplier = 1024 * 1024 * 1024; | 
| 199 | 0 |     } | 
| 200 |  | 
 | 
| 201 | 0 |     return toInt(s.substr(0, index), 1) * multiplier; | 
| 202 | 0 |   } | 
| 203 |  |  | 
| 204 | 0 |   return toInt(s, 1); | 
| 205 | 0 | } | 
| 206 |  |  | 
| 207 |  | LogString OptionConverter::findAndSubst(const LogString& key, Properties& props) | 
| 208 | 0 | { | 
| 209 | 0 |   LogString value(props.getProperty(key)); | 
| 210 |  | 
 | 
| 211 | 0 |   if (value.empty()) | 
| 212 | 0 |   { | 
| 213 | 0 |     return value; | 
| 214 | 0 |   } | 
| 215 |  |  | 
| 216 | 0 |   try | 
| 217 | 0 |   { | 
| 218 | 0 |     return substVars(value, props); | 
| 219 | 0 |   } | 
| 220 | 0 |   catch (IllegalArgumentException& e) | 
| 221 | 0 |   { | 
| 222 | 0 |     LogLog::error(((LogString) LOG4CXX_STR("Bad option value [")) | 
| 223 | 0 |       + value + LOG4CXX_STR("]."), e); | 
| 224 | 0 |     return value; | 
| 225 | 0 |   } | 
| 226 | 0 | } | 
| 227 |  |  | 
| 228 |  | LogString OptionConverter::substVars(const LogString& val, Properties& props) | 
| 229 | 1.12k | { | 
| 230 | 1.12k |   LogString sbuf; | 
| 231 | 1.12k |   const logchar delimStartArray[] = { 0x24, 0x7B, 0 }; // '$', '{' | 
| 232 | 1.12k |   const LogString delimStart(delimStartArray); | 
| 233 | 1.12k |   const logchar delimStop = 0x7D; // '}'; | 
| 234 | 1.12k |   const size_t DELIM_START_LEN = 2; | 
| 235 | 1.12k |   const size_t DELIM_STOP_LEN = 1; | 
| 236 |  |  | 
| 237 | 1.12k |   size_t i = 0; | 
| 238 |  |  | 
| 239 | 1.12k |   while (true) | 
| 240 | 1.12k |   { | 
| 241 | 1.12k |     size_t j = val.find(delimStart, i); | 
| 242 |  |  | 
| 243 | 1.12k |     if (j == val.npos) | 
| 244 | 1.12k |     { | 
| 245 |  |       // no more variables | 
| 246 | 1.12k |       if (i == 0) | 
| 247 | 1.12k |       { | 
| 248 |  |         // this is a simple string | 
| 249 | 1.12k |         return val; | 
| 250 | 1.12k |       } | 
| 251 | 0 |       else | 
| 252 | 0 |       { | 
| 253 |  |         // add the tail string which contails no variables and return the result. | 
| 254 | 0 |         sbuf.append(val.substr(i, val.length() - i)); | 
| 255 | 0 |         return sbuf; | 
| 256 | 0 |       } | 
| 257 | 1.12k |     } | 
| 258 | 0 |     else | 
| 259 | 0 |     { | 
| 260 | 0 |       sbuf.append(val.substr(i, j - i)); | 
| 261 | 0 |       size_t k = val.find(delimStop, j); | 
| 262 |  | 
 | 
| 263 | 0 |       if (k == val.npos) | 
| 264 | 0 |       { | 
| 265 | 0 |         LogString msg(1, (logchar) 0x22 /* '\"' */); | 
| 266 | 0 |         msg.append(val); | 
| 267 | 0 |         msg.append(LOG4CXX_STR("\" has no closing brace. Opening brace at position ")); | 
| 268 | 0 |         Pool p; | 
| 269 | 0 |         StringHelper::toString(j, p, msg); | 
| 270 | 0 |         msg.append(1, (logchar) 0x2E /* '.' */); | 
| 271 | 0 |         throw IllegalArgumentException(msg); | 
| 272 | 0 |       } | 
| 273 | 0 |       else | 
| 274 | 0 |       { | 
| 275 | 0 |         j += DELIM_START_LEN; | 
| 276 | 0 |         LogString key = val.substr(j, k - j); | 
| 277 |  |         // first try in System properties | 
| 278 | 0 |         LogString replacement(getSystemProperty(key, LogString())); | 
| 279 |  |  | 
| 280 |  |         // then try props parameter | 
| 281 | 0 |         if (replacement.empty()) | 
| 282 | 0 |         { | 
| 283 | 0 |           replacement = props.getProperty(key); | 
| 284 | 0 |         } | 
| 285 |  | 
 | 
| 286 | 0 |         if (!replacement.empty()) | 
| 287 | 0 |         { | 
| 288 |  |           // Do variable substitution on the replacement string | 
| 289 |  |           // such that we can solve "Hello ${x2}" as "Hello p1" | 
| 290 |  |           // the where the properties are | 
| 291 |  |           // x1=p1 | 
| 292 |  |           // x2=${x1} | 
| 293 | 0 |           LogString recursiveReplacement = substVars(replacement, props); | 
| 294 | 0 |           sbuf.append(recursiveReplacement); | 
| 295 | 0 |         } | 
| 296 |  | 
 | 
| 297 | 0 |         i = k + DELIM_STOP_LEN; | 
| 298 | 0 |       } | 
| 299 | 0 |     } | 
| 300 | 1.12k |   } | 
| 301 | 1.12k | } | 
| 302 |  |  | 
| 303 |  | LogString OptionConverter::getSystemProperty(const LogString& key, const LogString& def) | 
| 304 | 2 | { | 
| 305 | 2 |   if (!key.empty()) | 
| 306 | 2 |   { | 
| 307 | 2 |     LogString value(System::getProperty(key)); | 
| 308 |  |  | 
| 309 | 2 |     if (!value.empty()) | 
| 310 | 0 |     { | 
| 311 | 0 |       return value; | 
| 312 | 0 |     } | 
| 313 | 2 |   } | 
| 314 |  |  | 
| 315 | 2 |   return def; | 
| 316 | 2 | } | 
| 317 |  |  | 
| 318 |  | LevelPtr OptionConverter::toLevel(const LogString& value, | 
| 319 |  |   const LevelPtr& defaultValue) | 
| 320 | 0 | { | 
| 321 | 0 |   size_t hashIndex = value.find(LOG4CXX_STR("#")); | 
| 322 |  | 
 | 
| 323 | 0 |   if (hashIndex == LogString::npos) | 
| 324 | 0 |   { | 
| 325 |  |     // no class name specified : use standard Level class | 
| 326 | 0 |     if (value.empty()) | 
| 327 | 0 |     { | 
| 328 | 0 |       return defaultValue; | 
| 329 | 0 |     } | 
| 330 | 0 |     else | 
| 331 | 0 |     { | 
| 332 | 0 |       return Level::toLevelLS(value, defaultValue); | 
| 333 | 0 |     } | 
| 334 | 0 |   } | 
| 335 |  |  | 
| 336 | 0 |   LogString clazz = value.substr(hashIndex + 1); | 
| 337 | 0 |   LogString levelName = value.substr(0, hashIndex); | 
| 338 |  |  | 
| 339 |  |   // This is degenerate case but you never know. | 
| 340 | 0 |   if (levelName.empty() || clazz.empty()) | 
| 341 | 0 |   { | 
| 342 | 0 |     return Level::toLevelLS(value, defaultValue); | 
| 343 | 0 |   } | 
| 344 | 0 |   if (LogLog::isDebugEnabled()) | 
| 345 | 0 |   { | 
| 346 | 0 |     LogLog::debug(LOG4CXX_STR("Desired ") + Level::getStaticClass().getName() | 
| 347 | 0 |         + LOG4CXX_STR(" sub-class: [") + clazz + LOG4CXX_STR("]")); | 
| 348 | 0 |   } | 
| 349 |  | 
 | 
| 350 | 0 |   try | 
| 351 | 0 |   { | 
| 352 |  |     // Note: the dynamic_cast could fail across DLL boundaries. | 
| 353 |  |     // However, without the dynamic_cast a poorly formed XML file | 
| 354 |  |     // could attempt to load an invalid class as a filter, causing | 
| 355 |  |     // a crash.  If it can't be converted, a std::bad_cast should be | 
| 356 |  |     // thrown(and caught by the exception handler below) | 
| 357 | 0 |     const Level::LevelClass& levelClass = | 
| 358 | 0 |       dynamic_cast<const Level::LevelClass&>(Loader::loadClass(clazz)); | 
| 359 | 0 |     return levelClass.toLevel(levelName); | 
| 360 | 0 |   } | 
| 361 | 0 |   catch (Exception& oops) | 
| 362 | 0 |   { | 
| 363 | 0 |     LogLog::error(LOG4CXX_STR("Could not create ") + Level::getStaticClass().getName() + LOG4CXX_STR(" sub-class"), oops); | 
| 364 | 0 |   } | 
| 365 | 0 |   catch (const std::bad_cast&) | 
| 366 | 0 |   { | 
| 367 | 0 |     LogLog::warn( | 
| 368 | 0 |       LOG4CXX_STR("class [") + clazz + LOG4CXX_STR("] unable to be converted to " | 
| 369 | 0 |       "Level::LevelClass")); | 
| 370 | 0 |   } | 
| 371 | 0 |   catch (...) | 
| 372 | 0 |   { | 
| 373 | 0 |     LogLog::warn( | 
| 374 | 0 |       LOG4CXX_STR("class [") + clazz + LOG4CXX_STR("], level [") + levelName + | 
| 375 | 0 |       LOG4CXX_STR("] conversion) failed.")); | 
| 376 | 0 |   } | 
| 377 |  |  | 
| 378 | 0 |   return defaultValue; | 
| 379 | 0 | } | 
| 380 |  |  | 
| 381 |  |  | 
| 382 |  | ObjectPtr OptionConverter::instantiateByKey(Properties& props, const LogString& key, | 
| 383 |  |   const Class& superClass, const ObjectPtr& defaultValue) | 
| 384 | 0 | { | 
| 385 |  |   // Get the value of the property in string form | 
| 386 | 0 |   LogString className(findAndSubst(key, props)); | 
| 387 |  | 
 | 
| 388 | 0 |   if (className.empty()) | 
| 389 | 0 |   { | 
| 390 | 0 |     LogLog::error( | 
| 391 | 0 |       ((LogString) LOG4CXX_STR("Could not find value for key ")) + key); | 
| 392 | 0 |     return defaultValue; | 
| 393 | 0 |   } | 
| 394 |  |  | 
| 395 |  |   // Trim className to avoid trailing spaces that cause problems. | 
| 396 | 0 |   return OptionConverter::instantiateByClassName( | 
| 397 | 0 |       StringHelper::trim(className), superClass, defaultValue); | 
| 398 | 0 | } | 
| 399 |  |  | 
| 400 |  | ObjectPtr OptionConverter::instantiateByClassName(const LogString& className, | 
| 401 |  |   const Class& superClass, const ObjectPtr& defaultValue) | 
| 402 | 0 | { | 
| 403 | 0 |   if (LogLog::isDebugEnabled()) | 
| 404 | 0 |   { | 
| 405 | 0 |     LogLog::debug(LOG4CXX_STR("Desired ") + superClass.getName() | 
| 406 | 0 |       + LOG4CXX_STR(" sub-class: [") + className + LOG4CXX_STR("]")); | 
| 407 | 0 |   } | 
| 408 | 0 |   try | 
| 409 | 0 |   { | 
| 410 | 0 |     const Class& classObj = Loader::loadClass(className); | 
| 411 | 0 |     ObjectPtr newObject =  ObjectPtr(classObj.newInstance()); | 
| 412 |  | 
 | 
| 413 | 0 |     if (!newObject->instanceof(superClass)) | 
| 414 | 0 |     { | 
| 415 | 0 |       LogLog::error(LOG4CXX_STR("Not a ") + superClass.getName() + LOG4CXX_STR(" sub-class")); | 
| 416 | 0 |       return defaultValue; | 
| 417 | 0 |     } | 
| 418 |  |  | 
| 419 | 0 |     return newObject; | 
| 420 | 0 |   } | 
| 421 | 0 |   catch (Exception& e) | 
| 422 | 0 |   { | 
| 423 | 0 |     LogLog::error(LOG4CXX_STR("Could not create ") + superClass.getName() + LOG4CXX_STR(" sub-class"), e); | 
| 424 | 0 |   } | 
| 425 |  |  | 
| 426 | 0 |   return defaultValue; | 
| 427 | 0 | } | 
| 428 |  |  | 
| 429 |  | void OptionConverter::selectAndConfigure(const File& configFileName, | 
| 430 |  |   const LogString& _clazz, spi::LoggerRepositoryPtr hierarchy, int delay) | 
| 431 | 0 | { | 
| 432 | 0 |   ConfiguratorPtr configurator; | 
| 433 | 0 |   LogString clazz = _clazz; | 
| 434 |  | 
 | 
| 435 | 0 |   LogString filename(configFileName.getPath()); | 
| 436 |  | 
 | 
| 437 | 0 | #if LOG4CXX_HAS_DOMCONFIGURATOR | 
| 438 | 0 |   if (clazz.empty() | 
| 439 | 0 |     && filename.length() > 4 | 
| 440 | 0 |     && StringHelper::equalsIgnoreCase( | 
| 441 | 0 |       filename.substr(filename.length() - 4), | 
| 442 | 0 |       LOG4CXX_STR(".XML"), LOG4CXX_STR(".xml"))) | 
| 443 | 0 |   { | 
| 444 | 0 |     clazz = LOG4CXX_NS::xml::DOMConfigurator::getStaticClass().getName(); | 
| 445 | 0 |   } | 
| 446 | 0 | #endif | 
| 447 |  | 
 | 
| 448 | 0 |   if (!clazz.empty()) | 
| 449 | 0 |   { | 
| 450 | 0 |     if (LogLog::isDebugEnabled()) | 
| 451 | 0 |       LogLog::debug(LOG4CXX_STR("Preferred configurator class: ") + clazz); | 
| 452 | 0 |     const Class& clazzObj = Loader::loadClass(clazz); | 
| 453 | 0 |     ObjectPtr obj = ObjectPtr(clazzObj.newInstance()); | 
| 454 | 0 |     configurator = LOG4CXX_NS::cast<Configurator>(obj); | 
| 455 |  | 
 | 
| 456 | 0 |     if (configurator == 0) | 
| 457 | 0 |     { | 
| 458 | 0 |       LogLog::error(LOG4CXX_STR("Could not instantiate configurator [") | 
| 459 | 0 |         + clazz + LOG4CXX_STR("].")); | 
| 460 | 0 |       return; | 
| 461 | 0 |     } | 
| 462 | 0 |   } | 
| 463 | 0 |   else | 
| 464 | 0 |   { | 
| 465 | 0 |     configurator = std::make_shared<PropertyConfigurator>(); | 
| 466 | 0 |   } | 
| 467 |  |  | 
| 468 | 0 |   if (0 < delay) | 
| 469 | 0 |     ConfiguratorWatchdog::startWatching(configurator, configFileName, delay); | 
| 470 | 0 |   else | 
| 471 | 0 |     configurator->doConfigure(configFileName, hierarchy); | 
| 472 | 0 | } |