Index: src/domconfigurator.cpp =================================================================== --- src/domconfigurator.cpp (revision 472158) +++ src/domconfigurator.cpp (working copy) @@ -770,7 +770,7 @@ LogString debugAttrib = subst(getAttribute(element, INTERNAL_DEBUG_ATTR)); - static const LogString NuLL(LOG4CXX_STR("NULL")); + const LogString NuLL(LOG4CXX_STR("NULL")); LogLog::debug(LOG4CXX_STR("debug attribute= \"") + debugAttrib +LOG4CXX_STR("\".")); // if the log4j.dtd is not specified in the XML file, then the // "debug" attribute is returned as the empty string. Index: src/transform.cpp =================================================================== --- src/transform.cpp (revision 472158) +++ src/transform.cpp (working copy) @@ -54,15 +54,23 @@ } } +const LogString &Transform::CDATA_END() { + static const LogString str(LOG4CXX_STR("]]>")); + return str; +} + +const LogString &Transform::CDATA_EMBEDED_END() { + static const LogString str(LOG4CXX_STR("]]>]]>")); - static const LogString CDATA_EMBEDED_END(LOG4CXX_STR("]]>]]> +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace log4cxx; +using namespace log4cxx::helpers; +using namespace log4cxx::pattern; +using namespace log4cxx::rolling; +using namespace log4cxx::spi; + +long StaticInitializer::initCount = 0; + +// Call every function that contains static locals to force +// their construction so that they don't get destructed +// before user's static variables. +void StaticInitializer::initAll() { + APRInitializer::getInstance(); + CharsetDecoder::getDefaultDecoder(); + CharsetDecoder::getUTF8Decoder(); +#if LOG4CXX_HAS_WCHAR_T + CharsetDecoder::getWideDecoder(); +#endif + CharsetEncoder::getDefaultEncoder(); +#if LOG4CXX_HAS_WCHAR_T + CharsetDecoder::getWideDecoder(); +#endif + Class::getRegistry(); + ClassNamePatternConverter::newInstance(std::vector ()); + ConsoleAppender::getSystemOut(); + ConsoleAppender::getSystemErr(); + DefaultConfigurator::getConfigurationFileName(); + FileLocationPatternConverter::newInstance(std::vector ()); + { + FixedWindowRollingPolicy tmp; + tmp.getFormatSpecifiers(); + }; + FormattingInfo::getDefault(); + FullLocationPatternConverter::newInstance(std::vector ()); + IntegerPatternConverter::newInstance(std::vector ()); + LevelPatternConverter::newInstance(std::vector ()); + LineLocationPatternConverter::newInstance(std::vector ()); + LineSeparatorPatternConverter::newInstance(std::vector ()); + LiteralPatternConverter::newInstance (" "); + LocationInfo::getLocationUnavailable(); + LoggerPatternConverter::newInstance(std::vector ()); + LogManager::getRepositorySelector(); + MessagePatternConverter::newInstance(std::vector ()); + MethodLocationPatternConverter::newInstance(std::vector ()); + NameAbbreviator::getDefaultAbbreviator(); + NDC::getNull(); + NDCPatternConverter::newInstance(std::vector ()); + { + PatternLayout::TTCC_CONVERSION_PATTERN(); + PatternLayout tmp; + tmp.getFormatSpecifiers(); + }; + PropertiesPatternConverter::newInstance(std::vector ()); + RelativeTimePatternConverter::newInstance(std::vector ()); + ThreadPatternConverter::newInstance(std::vector ()); + ThreadSpecificData::getCurrentData(); + ThrowableInformationPatternConverter::newInstance (std::vector ()); + ThrowableInformationPatternConverter::newInstance (std::vector (1, "short")); + { + TimeBasedRollingPolicy tmp; + tmp.getFormatSpecifiers(); + }; + TimeZone::getDefault(); + TimeZone::getGMT(); + Transform::CDATA_END(); + Transform::CDATA_EMBEDED_END(); +} + +// This constructor gets executed once per each user's translation unit +// (via #include . The first tme it is called it initializes +// all local staticvariables used throughout log4cxx code. +StaticInitializer::StaticInitializer() { + if (initCount == 0) + initAll(); + ++initCount; +} + +StaticInitializer::~StaticInitializer() { + assert (initCount > 0); + --initCount; +} + Index: src/basicconfigurator.cpp =================================================================== --- src/basicconfigurator.cpp (revision 472158) +++ src/basicconfigurator.cpp (working copy) @@ -26,8 +26,7 @@ { LogManager::getLoggerRepository()->setConfigured(true); LoggerPtr root = Logger::getRootLogger(); - static const LogString TTCC_CONVERSION_PATTERN(LOG4CXX_STR("%r [%t] %p %c %x - %m%n")); - LayoutPtr layout(new PatternLayout(TTCC_CONVERSION_PATTERN)); + LayoutPtr layout(new PatternLayout(PatternLayout::TTCC_CONVERSION_PATTERN())); AppenderPtr appender(new ConsoleAppender(layout)); root->addAppender(appender); } Index: src/propertyconfigurator.cpp =================================================================== --- src/propertyconfigurator.cpp (revision 472158) +++ src/propertyconfigurator.cpp (working copy) @@ -133,7 +133,7 @@ { hierarchy->setConfigured(true); - static const LogString DEBUG_KEY(LOG4CXX_STR("log4j.debug")); + const LogString DEBUG_KEY(LOG4CXX_STR("log4j.debug")); LogString value(properties.getProperty(DEBUG_KEY)); if (!value.empty()) @@ -141,7 +141,7 @@ LogLog::setInternalDebugging(OptionConverter::toBoolean(value, true)); } - static const LogString THRESHOLD_PREFIX(LOG4CXX_STR("log4j.threshold")); + const LogString THRESHOLD_PREFIX(LOG4CXX_STR("log4j.threshold")); LogString thresholdStr = OptionConverter::findAndSubst(THRESHOLD_PREFIX, properties); @@ -166,7 +166,7 @@ void PropertyConfigurator::configureLoggerFactory(helpers::Properties& props) { - static const LogString LOGGER_FACTORY_KEY(LOG4CXX_STR("log4j.loggerFactory")); + const LogString LOGGER_FACTORY_KEY(LOG4CXX_STR("log4j.loggerFactory")); LogString factoryClassName = OptionConverter::findAndSubst(LOGGER_FACTORY_KEY, props); @@ -180,7 +180,7 @@ loggerFactory = OptionConverter::instantiateByClassName( factoryClassName, LoggerFactory::getStaticClass(), loggerFactory); - static const LogString FACTORY_PREFIX(LOG4CXX_STR("log4j.factory.")); + const LogString FACTORY_PREFIX(LOG4CXX_STR("log4j.factory.")); Pool p; PropertySetter::setProperties(loggerFactory, props, FACTORY_PREFIX, p); } @@ -189,8 +189,8 @@ void PropertyConfigurator::configureRootCategory(helpers::Properties& props, spi::LoggerRepositoryPtr& hierarchy) { - static const LogString ROOT_CATEGORY_PREFIX(LOG4CXX_STR("log4j.rootCategory")); - static const LogString ROOT_LOGGER_PREFIX(LOG4CXX_STR("log4j.rootLogger")); + const LogString ROOT_CATEGORY_PREFIX(LOG4CXX_STR("log4j.rootCategory")); + const LogString ROOT_LOGGER_PREFIX(LOG4CXX_STR("log4j.rootLogger")); @@ -212,7 +212,7 @@ LoggerPtr root = hierarchy->getRootLogger(); synchronized sync(root->getMutex()); - static const LogString INTERNAL_ROOT_NAME(LOG4CXX_STR("root")); + const LogString INTERNAL_ROOT_NAME(LOG4CXX_STR("root")); parseCategory(props, root, effectiveFrefix, INTERNAL_ROOT_NAME, value); } } @@ -220,8 +220,8 @@ void PropertyConfigurator::parseCatsAndRenderers(helpers::Properties& props, spi::LoggerRepositoryPtr& hierarchy) { - static const LogString CATEGORY_PREFIX(LOG4CXX_STR("log4j.category.")); - static const LogString LOGGER_PREFIX(LOG4CXX_STR("log4j.logger.")); + const LogString CATEGORY_PREFIX(LOG4CXX_STR("log4j.category.")); + const LogString LOGGER_PREFIX(LOG4CXX_STR("log4j.logger.")); std::vector names = props.propertyNames(); @@ -258,7 +258,7 @@ LoggerPtr& cat, const LogString& loggerName) { - static const LogString ADDITIVITY_PREFIX(LOG4CXX_STR("log4j.additivity.")); + const LogString ADDITIVITY_PREFIX(LOG4CXX_STR("log4j.additivity.")); @@ -314,7 +314,7 @@ if (StringHelper::equalsIgnoreCase(levelStr, LOG4CXX_STR("INHERITED"), LOG4CXX_STR("inherited")) || StringHelper::equalsIgnoreCase(levelStr, LOG4CXX_STR("NULL"), LOG4CXX_STR("null"))) { - static const LogString INTERNAL_ROOT_NAME(LOG4CXX_STR("root")); + const LogString INTERNAL_ROOT_NAME(LOG4CXX_STR("root")); if (loggerName == INTERNAL_ROOT_NAME) { LogLog::warn(LOG4CXX_STR("The root logger cannot be set to null.")); @@ -373,7 +373,7 @@ return appender; } - static const LogString APPENDER_PREFIX(LOG4CXX_STR("log4j.appender.")); + const LogString APPENDER_PREFIX(LOG4CXX_STR("log4j.appender.")); // Appender was not previously initialized. LogString prefix = APPENDER_PREFIX + appenderName; Index: src/transcoder.cpp =================================================================== --- src/transcoder.cpp (revision 472158) +++ src/transcoder.cpp (working copy) @@ -53,7 +53,7 @@ * internal string. */ void Transcoder::decode(const char* src, size_t len, LogString& dst) { - static CharsetDecoderPtr decoder(CharsetDecoder::getDefaultDecoder()); + CharsetDecoderPtr decoder(CharsetDecoder::getDefaultDecoder()); if (len > 0) { ByteBuffer buf((char*) src, len); while(buf.remaining() > 0) { @@ -68,7 +68,7 @@ } void Transcoder::encode(const LogString& src, std::string& dst) { - static CharsetEncoderPtr encoder(CharsetEncoder::getDefaultEncoder()); + CharsetEncoderPtr encoder(CharsetEncoder::getDefaultEncoder()); if (src.length() > 0) { char buf[BUFSIZE]; ByteBuffer out(buf, BUFSIZE); @@ -109,7 +109,7 @@ #if LOG4CXX_LOGCHAR_IS_UTF8 && LOG4CXX_HAS_WCHAR_T void Transcoder::decode(const wchar_t* src, size_t len, LogString& dst) { - static CharsetDecoderPtr decoder(CharsetDecoder::getWideDecoder()); + CharsetDecoderPtr decoder(CharsetDecoder::getWideDecoder()); if (len > 0) { ByteBuffer buf((char*) src, len * sizeof(wchar_t)); while(buf.remaining() > 0) { @@ -124,7 +124,7 @@ } void Transcoder::encode(const LogString& src, std::wstring& dst) { - static CharsetEncoderPtr encoder(CharsetEncoder::getWideEncoder()); + CharsetEncoderPtr encoder(CharsetEncoder::getWideEncoder()); if (src.length() > 0) { char buf[BUFSIZE]; ByteBuffer out(buf, BUFSIZE); Index: src/optionconverter.cpp =================================================================== --- src/optionconverter.cpp (revision 472158) +++ src/optionconverter.cpp (working copy) @@ -173,7 +173,7 @@ LogString OptionConverter::substVars(const LogString& val, Properties& props) { LogString sbuf; - static const LogString delimStart(LOG4CXX_STR("${")); + const LogString delimStart(LOG4CXX_STR("${")); const logchar delimStop = LOG4CXX_STR('}'); const size_t DELIM_START_LEN = 2; const size_t DELIM_STOP_LEN = 1; Index: src/patternlayout.cpp =================================================================== --- src/patternlayout.cpp (revision 472158) +++ src/patternlayout.cpp (working copy) @@ -65,6 +65,11 @@ activateOptions(pool); } +const LogString &PatternLayout::TTCC_CONVERSION_PATTERN() { + static const LogString pattern(LOG4CXX_STR("%r [%t] %p %c %x - %m%n")); + return pattern; +} + void PatternLayout::setConversionPattern(const LogString& pattern) { conversionPattern = pattern; Index: include/log4cxx/log4cxx.h.in =================================================================== --- include/log4cxx/log4cxx.h.in (revision 472158) +++ include/log4cxx/log4cxx.h.in (working copy) @@ -37,5 +37,5 @@ typedef int log4cxx_status_t; typedef unsigned int log4cxx_uint32_t; - +#include #endif Index: include/log4cxx/ndc.h =================================================================== --- include/log4cxx/ndc.h (revision 472158) +++ include/log4cxx/ndc.h (working copy) @@ -96,6 +96,7 @@ class LOG4CXX_EXPORT NDC { private: + friend class helpers::StaticInitializer; class DiagnosticContext { public: Index: include/log4cxx/patternlayout.h =================================================================== --- include/log4cxx/patternlayout.h (revision 472158) +++ include/log4cxx/patternlayout.h (working copy) @@ -320,6 +320,8 @@ */ class LOG4CXX_EXPORT PatternLayout : public Layout { + friend class helpers::StaticInitializer; + /** * Conversion pattern. */ @@ -354,6 +356,11 @@ PatternLayout(const LogString& pattern); /** + * Returns TTCC pattern string ("%r [%t] %p %c %x - %m%n") + */ + static const LogString &TTCC_CONVERSION_PATTERN(); + + /** Set the ConversionPattern option. This is the string which controls formatting and consists of a mix of literal content and conversion specifiers. Index: include/log4cxx/helpers/class.h =================================================================== --- include/log4cxx/helpers/class.h (revision 472158) +++ include/log4cxx/helpers/class.h (working copy) @@ -43,6 +43,7 @@ Class(); private: + friend class StaticInitializer; Class(const Class&); Class& operator=(const Class&); typedef std::map ClassMap; Index: include/log4cxx/helpers/transform.h =================================================================== --- include/log4cxx/helpers/transform.h (revision 472158) +++ include/log4cxx/helpers/transform.h (working copy) @@ -54,6 +54,10 @@ */ static void appendEscapingCDATA( LogString& buf, const LogString& input); + private: + friend class helpers::StaticInitializer; + static const LogString &CDATA_END(); + static const LogString &CDATA_EMBEDED_END(); }; // class Transform } // namespace helpers } //namespace log4cxx Index: include/log4cxx/helpers/aprinitializer.h =================================================================== --- include/log4cxx/helpers/aprinitializer.h (revision 472158) +++ include/log4cxx/helpers/aprinitializer.h (working copy) @@ -38,6 +38,7 @@ static bool isDestructed; private: + friend class StaticInitializer; APRInitializer(); APRInitializer(const APRInitializer&); APRInitializer& operator=(const APRInitializer&); Index: include/log4cxx/helpers/staticinitializer.h =================================================================== --- include/log4cxx/helpers/staticinitializer.h (revision 0) +++ include/log4cxx/helpers/staticinitializer.h (revision 0) @@ -0,0 +1,29 @@ +#ifndef _LOG4CXX_HELPERS_STATIC_INITIALIZER_H +#define _LOG4CXX_HELPERS_STATIC_INITIALIZER_H + +namespace log4cxx +{ + namespace helpers + { + /** + * Initialize static variables used throughout this library. + * A static instance of this class is created in each user + * translation unit, via #include . + * Its constructor initializes all global vars used in log4cxx. + */ + class LOG4CXX_EXPORT StaticInitializer + { + public: + StaticInitializer(); + ~StaticInitializer(); + private: + static long initCount; + static void initAll(); + }; +#if !defined LOG4CXX && !defined LOG4CXX_NO_AUTO_INIT + static StaticInitializer _staticInitializerInstance; +#endif + } +} + +#endif Index: include/log4cxx/helpers/threadspecificdata.h =================================================================== --- include/log4cxx/helpers/threadspecificdata.h (revision 472158) +++ include/log4cxx/helpers/threadspecificdata.h (working copy) @@ -39,6 +39,7 @@ static log4cxx::MDC::Map& getCurrentThreadMap(); private: + friend class StaticInitializer; static ThreadSpecificData& getCurrentData(); log4cxx::NDC::Stack ndcStack; log4cxx::MDC::Map mdcMap; Index: include/log4cxx/log4cxx.hw =================================================================== --- include/log4cxx/log4cxx.hw (revision 472158) +++ include/log4cxx/log4cxx.hw (working copy) @@ -59,5 +59,6 @@ #define LOG4CXX_HAVE_ODBC 1 #endif +#include #endif Index: include/log4cxx/rolling/fixedwindowrollingpolicy.h =================================================================== --- include/log4cxx/rolling/fixedwindowrollingpolicy.h (revision 472158) +++ include/log4cxx/rolling/fixedwindowrollingpolicy.h (working copy) @@ -76,6 +76,7 @@ int maxIndex; bool explicitActiveFile; + friend class helpers::StaticInitializer; /** * It's almost always a bad idea to have a large window size, say over 12. */ Index: include/log4cxx/rolling/timebasedrollingpolicy.h =================================================================== --- include/log4cxx/rolling/timebasedrollingpolicy.h (revision 472158) +++ include/log4cxx/rolling/timebasedrollingpolicy.h (working copy) @@ -145,6 +145,9 @@ END_LOG4CXX_CAST_MAP() private: + + friend class helpers::StaticInitializer; + /** * Time for next determination if time for rollover. */ Index: include/log4cxx/defaultconfigurator.h =================================================================== --- include/log4cxx/defaultconfigurator.h (revision 472158) +++ include/log4cxx/defaultconfigurator.h (working copy) @@ -33,6 +33,7 @@ class LOG4CXX_EXPORT DefaultConfigurator { private: + friend class helpers::StaticInitializer; DefaultConfigurator() {} public: Index: include/log4cxx/logmanager.h =================================================================== --- include/log4cxx/logmanager.h (revision 472158) +++ include/log4cxx/logmanager.h (working copy) @@ -41,6 +41,7 @@ class LOG4CXX_EXPORT LogManager { private: + friend class helpers::StaticInitializer; static void * guard; static spi::RepositorySelectorPtr& getRepositorySelector();