12a97ec55SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 32a97ec55SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 42a97ec55SAndrew Rist * or more contributor license agreements. See the NOTICE file 52a97ec55SAndrew Rist * distributed with this work for additional information 62a97ec55SAndrew Rist * regarding copyright ownership. The ASF licenses this file 72a97ec55SAndrew Rist * to you under the Apache License, Version 2.0 (the 82a97ec55SAndrew Rist * "License"); you may not use this file except in compliance 92a97ec55SAndrew Rist * with the License. You may obtain a copy of the License at 102a97ec55SAndrew Rist * 112a97ec55SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 122a97ec55SAndrew Rist * 132a97ec55SAndrew Rist * Unless required by applicable law or agreed to in writing, 142a97ec55SAndrew Rist * software distributed under the License is distributed on an 152a97ec55SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 162a97ec55SAndrew Rist * KIND, either express or implied. See the License for the 172a97ec55SAndrew Rist * specific language governing permissions and limitations 182a97ec55SAndrew Rist * under the License. 192a97ec55SAndrew Rist * 202a97ec55SAndrew Rist *************************************************************/ 212a97ec55SAndrew Rist 222a97ec55SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_extensions.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include "loggerconfig.hxx" 28*197bf4dcSAriel Constenla-Haile #include <stdio.h> 29cdf0e10cSrcweir 30cdf0e10cSrcweir /** === begin UNO includes === **/ 31cdf0e10cSrcweir #include <com/sun/star/lang/XMultiServiceFactory.hpp> 32cdf0e10cSrcweir #include <com/sun/star/container/XNameContainer.hpp> 33cdf0e10cSrcweir #include <com/sun/star/lang/XSingleServiceFactory.hpp> 34cdf0e10cSrcweir #include <com/sun/star/util/XChangesBatch.hpp> 35cdf0e10cSrcweir #include <com/sun/star/logging/LogLevel.hpp> 36cdf0e10cSrcweir #include <com/sun/star/lang/NullPointerException.hpp> 37cdf0e10cSrcweir #include <com/sun/star/lang/ServiceNotRegisteredException.hpp> 38cdf0e10cSrcweir #include <com/sun/star/beans/NamedValue.hpp> 39cdf0e10cSrcweir #include <com/sun/star/logging/XLogHandler.hpp> 40cdf0e10cSrcweir #include <com/sun/star/logging/XLogFormatter.hpp> 41cdf0e10cSrcweir /** === end UNO includes === **/ 42cdf0e10cSrcweir 43cdf0e10cSrcweir #include <tools/diagnose_ex.h> 44*197bf4dcSAriel Constenla-Haile #include <osl/process.h> 45*197bf4dcSAriel Constenla-Haile #include <rtl/ustrbuf.hxx> 46cdf0e10cSrcweir 47cdf0e10cSrcweir #include <comphelper/componentcontext.hxx> 48cdf0e10cSrcweir 49cdf0e10cSrcweir #include <cppuhelper/component_context.hxx> 50cdf0e10cSrcweir 51cdf0e10cSrcweir #include <vector> 52cdf0e10cSrcweir 53cdf0e10cSrcweir //........................................................................ 54cdf0e10cSrcweir namespace logging 55cdf0e10cSrcweir { 56cdf0e10cSrcweir //........................................................................ 57cdf0e10cSrcweir 58cdf0e10cSrcweir /** === begin UNO using === **/ 59cdf0e10cSrcweir using ::com::sun::star::uno::Reference; 60cdf0e10cSrcweir using ::com::sun::star::logging::XLogger; 61cdf0e10cSrcweir using ::com::sun::star::lang::XMultiServiceFactory; 62cdf0e10cSrcweir using ::com::sun::star::uno::Sequence; 63cdf0e10cSrcweir using ::com::sun::star::uno::Any; 64cdf0e10cSrcweir using ::com::sun::star::container::XNameContainer; 65cdf0e10cSrcweir using ::com::sun::star::uno::UNO_QUERY_THROW; 66cdf0e10cSrcweir using ::com::sun::star::lang::XSingleServiceFactory; 67cdf0e10cSrcweir using ::com::sun::star::uno::XInterface; 68cdf0e10cSrcweir using ::com::sun::star::util::XChangesBatch; 69cdf0e10cSrcweir using ::com::sun::star::uno::makeAny; 70cdf0e10cSrcweir using ::com::sun::star::lang::NullPointerException; 71cdf0e10cSrcweir using ::com::sun::star::uno::Exception; 72cdf0e10cSrcweir using ::com::sun::star::lang::ServiceNotRegisteredException; 73cdf0e10cSrcweir using ::com::sun::star::beans::NamedValue; 74cdf0e10cSrcweir using ::com::sun::star::logging::XLogHandler; 75cdf0e10cSrcweir using ::com::sun::star::logging::XLogFormatter; 76cdf0e10cSrcweir using ::com::sun::star::container::XNameAccess; 77cdf0e10cSrcweir using ::com::sun::star::uno::XComponentContext; 78cdf0e10cSrcweir /** === end UNO using === **/ 79cdf0e10cSrcweir namespace LogLevel = ::com::sun::star::logging::LogLevel; 80cdf0e10cSrcweir 81cdf0e10cSrcweir namespace 82cdf0e10cSrcweir { 83cdf0e10cSrcweir //---------------------------------------------------------------- 84cdf0e10cSrcweir typedef void (*SettingTranslation)( const Reference< XLogger >&, const ::rtl::OUString&, Any& ); 85cdf0e10cSrcweir 86cdf0e10cSrcweir //---------------------------------------------------------------- lcl_substituteFileHandlerURLVariables_nothrow(const Reference<XLogger> & _rxLogger,::rtl::OUString & _inout_rFileURL)87cdf0e10cSrcweir void lcl_substituteFileHandlerURLVariables_nothrow( const Reference< XLogger >& _rxLogger, ::rtl::OUString& _inout_rFileURL ) 88cdf0e10cSrcweir { 89cdf0e10cSrcweir struct Variable 90cdf0e10cSrcweir { 91cdf0e10cSrcweir const sal_Char* pVariablePattern; 92cdf0e10cSrcweir const sal_Int32 nPatternLength; 93cdf0e10cSrcweir rtl_TextEncoding eEncoding; 94cdf0e10cSrcweir const ::rtl::OUString sVariableValue; 95cdf0e10cSrcweir 96cdf0e10cSrcweir Variable( const sal_Char* _pVariablePattern, const sal_Int32 _nPatternLength, rtl_TextEncoding _eEncoding, 97cdf0e10cSrcweir const ::rtl::OUString& _rVariableValue ) 98cdf0e10cSrcweir :pVariablePattern( _pVariablePattern ) 99cdf0e10cSrcweir ,nPatternLength( _nPatternLength ) 100cdf0e10cSrcweir ,eEncoding( _eEncoding ) 101cdf0e10cSrcweir ,sVariableValue( _rVariableValue ) 102cdf0e10cSrcweir { 103cdf0e10cSrcweir } 104cdf0e10cSrcweir }; 105cdf0e10cSrcweir 106cdf0e10cSrcweir ::rtl::OUString sLoggerName; 107cdf0e10cSrcweir try { sLoggerName = _rxLogger->getName(); } 108cdf0e10cSrcweir catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } 109cdf0e10cSrcweir 110*197bf4dcSAriel Constenla-Haile TimeValue aTimeValue; 111*197bf4dcSAriel Constenla-Haile oslDateTime aDateTime; 112*197bf4dcSAriel Constenla-Haile OSL_VERIFY( osl_getSystemTime( &aTimeValue ) ); 113*197bf4dcSAriel Constenla-Haile OSL_VERIFY( osl_getDateTimeFromTimeValue( &aTimeValue, &aDateTime ) ); 114*197bf4dcSAriel Constenla-Haile 115*197bf4dcSAriel Constenla-Haile char buffer[ 30 ]; 116*197bf4dcSAriel Constenla-Haile const size_t buffer_size = sizeof( buffer ); 117*197bf4dcSAriel Constenla-Haile 118*197bf4dcSAriel Constenla-Haile snprintf( buffer, buffer_size, "%04i-%02i-%02i", 119*197bf4dcSAriel Constenla-Haile (int)aDateTime.Year, 120*197bf4dcSAriel Constenla-Haile (int)aDateTime.Month, 121*197bf4dcSAriel Constenla-Haile (int)aDateTime.Day ); 122*197bf4dcSAriel Constenla-Haile rtl::OUString sDate = rtl::OUString::createFromAscii( buffer ); 123*197bf4dcSAriel Constenla-Haile 124*197bf4dcSAriel Constenla-Haile snprintf( buffer, buffer_size, "%02i-%02i-%02i.%03i", 125*197bf4dcSAriel Constenla-Haile (int)aDateTime.Hours, 126*197bf4dcSAriel Constenla-Haile (int)aDateTime.Minutes, 127*197bf4dcSAriel Constenla-Haile (int)aDateTime.Seconds, 128*197bf4dcSAriel Constenla-Haile ::sal::static_int_cast< sal_Int16 >( aDateTime.NanoSeconds / 10000000 ) ); 129*197bf4dcSAriel Constenla-Haile rtl::OUString sTime = rtl::OUString::createFromAscii( buffer ); 130*197bf4dcSAriel Constenla-Haile 131*197bf4dcSAriel Constenla-Haile rtl::OUStringBuffer aBuff; 132*197bf4dcSAriel Constenla-Haile aBuff.append( sDate ); 133*197bf4dcSAriel Constenla-Haile aBuff.append( sal_Unicode( '.' ) ); 134*197bf4dcSAriel Constenla-Haile aBuff.append( sTime ); 135*197bf4dcSAriel Constenla-Haile rtl::OUString sDateTime = aBuff.makeStringAndClear(); 136*197bf4dcSAriel Constenla-Haile 137*197bf4dcSAriel Constenla-Haile oslProcessIdentifier aProcessId = 0; 138*197bf4dcSAriel Constenla-Haile oslProcessInfo info; 139*197bf4dcSAriel Constenla-Haile info.Size = sizeof (oslProcessInfo); 140*197bf4dcSAriel Constenla-Haile if ( osl_getProcessInfo ( 0, osl_Process_IDENTIFIER, &info ) == osl_Process_E_None) 141*197bf4dcSAriel Constenla-Haile aProcessId = info.Ident; 142*197bf4dcSAriel Constenla-Haile rtl::OUString aPID = rtl::OUString::valueOf( sal_Int64( aProcessId ) ); 143*197bf4dcSAriel Constenla-Haile 144cdf0e10cSrcweir Variable aVariables[] = 145cdf0e10cSrcweir { 146*197bf4dcSAriel Constenla-Haile Variable( RTL_CONSTASCII_USTRINGPARAM( "$(loggername)" ), sLoggerName ), 147*197bf4dcSAriel Constenla-Haile Variable( RTL_CONSTASCII_USTRINGPARAM( "$(date)" ), sDate ), 148*197bf4dcSAriel Constenla-Haile Variable( RTL_CONSTASCII_USTRINGPARAM( "$(time)" ), sTime ), 149*197bf4dcSAriel Constenla-Haile Variable( RTL_CONSTASCII_USTRINGPARAM( "$(datetime)" ), sDateTime ), 150*197bf4dcSAriel Constenla-Haile Variable( RTL_CONSTASCII_USTRINGPARAM( "$(pid)" ), aPID ) 151cdf0e10cSrcweir }; 152cdf0e10cSrcweir 153cdf0e10cSrcweir for ( size_t i = 0; i < sizeof( aVariables ) / sizeof( aVariables[0] ); ++i ) 154cdf0e10cSrcweir { 155cdf0e10cSrcweir ::rtl::OUString sPattern( aVariables[i].pVariablePattern, aVariables[i].nPatternLength, aVariables[i].eEncoding ); 156cdf0e10cSrcweir sal_Int32 nVariableIndex = _inout_rFileURL.indexOf( sPattern ); 157cdf0e10cSrcweir if ( ( nVariableIndex == 0 ) 158cdf0e10cSrcweir || ( ( nVariableIndex > 0 ) 159cdf0e10cSrcweir && ( sPattern[ nVariableIndex - 1 ] != '$' ) 160cdf0e10cSrcweir ) 161cdf0e10cSrcweir ) 162cdf0e10cSrcweir { 163cdf0e10cSrcweir // found an (unescaped) variable 164cdf0e10cSrcweir _inout_rFileURL = _inout_rFileURL.replaceAt( nVariableIndex, sPattern.getLength(), aVariables[i].sVariableValue ); 165cdf0e10cSrcweir } 166cdf0e10cSrcweir } 167cdf0e10cSrcweir } 168cdf0e10cSrcweir 169cdf0e10cSrcweir //---------------------------------------------------------------- lcl_transformFileHandlerSettings_nothrow(const Reference<XLogger> & _rxLogger,const::rtl::OUString & _rSettingName,Any & _inout_rSettingValue)170cdf0e10cSrcweir void lcl_transformFileHandlerSettings_nothrow( const Reference< XLogger >& _rxLogger, const ::rtl::OUString& _rSettingName, Any& _inout_rSettingValue ) 171cdf0e10cSrcweir { 172cdf0e10cSrcweir if ( !_rSettingName.equalsAscii( "FileURL" ) ) 173cdf0e10cSrcweir // not interested in this setting 174cdf0e10cSrcweir return; 175cdf0e10cSrcweir 176cdf0e10cSrcweir ::rtl::OUString sURL; 177cdf0e10cSrcweir OSL_VERIFY( _inout_rSettingValue >>= sURL ); 178cdf0e10cSrcweir lcl_substituteFileHandlerURLVariables_nothrow( _rxLogger, sURL ); 179cdf0e10cSrcweir _inout_rSettingValue <<= sURL; 180cdf0e10cSrcweir } 181cdf0e10cSrcweir 182cdf0e10cSrcweir //---------------------------------------------------------------- lcl_createInstanceFromSetting_throw(const::comphelper::ComponentContext & _rContext,const Reference<XLogger> & _rxLogger,const Reference<XNameAccess> & _rxLoggerSettings,const sal_Char * _pServiceNameAsciiNodeName,const sal_Char * _pServiceSettingsAsciiNodeName,SettingTranslation _pSettingTranslation=NULL)183cdf0e10cSrcweir Reference< XInterface > lcl_createInstanceFromSetting_throw( 184cdf0e10cSrcweir const ::comphelper::ComponentContext& _rContext, 185cdf0e10cSrcweir const Reference< XLogger >& _rxLogger, 186cdf0e10cSrcweir const Reference< XNameAccess >& _rxLoggerSettings, 187cdf0e10cSrcweir const sal_Char* _pServiceNameAsciiNodeName, 188cdf0e10cSrcweir const sal_Char* _pServiceSettingsAsciiNodeName, 189cdf0e10cSrcweir SettingTranslation _pSettingTranslation = NULL 190cdf0e10cSrcweir ) 191cdf0e10cSrcweir { 192cdf0e10cSrcweir Reference< XInterface > xInstance; 193cdf0e10cSrcweir 194cdf0e10cSrcweir // read the settings for the to-be-created service 195cdf0e10cSrcweir Reference< XNameAccess > xServiceSettingsNode( _rxLoggerSettings->getByName( 196cdf0e10cSrcweir ::rtl::OUString::createFromAscii( _pServiceSettingsAsciiNodeName ) ), UNO_QUERY_THROW ); 197cdf0e10cSrcweir 198cdf0e10cSrcweir Sequence< ::rtl::OUString > aSettingNames( xServiceSettingsNode->getElementNames() ); 199cdf0e10cSrcweir size_t nServiceSettingCount( aSettingNames.getLength() ); 200cdf0e10cSrcweir Sequence< NamedValue > aSettings( nServiceSettingCount ); 201cdf0e10cSrcweir if ( nServiceSettingCount ) 202cdf0e10cSrcweir { 203cdf0e10cSrcweir const ::rtl::OUString* pSettingNames = aSettingNames.getConstArray(); 204cdf0e10cSrcweir const ::rtl::OUString* pSettingNamesEnd = aSettingNames.getConstArray() + aSettingNames.getLength(); 205cdf0e10cSrcweir NamedValue* pSetting = aSettings.getArray(); 206cdf0e10cSrcweir 207cdf0e10cSrcweir for ( ; 208cdf0e10cSrcweir pSettingNames != pSettingNamesEnd; 209cdf0e10cSrcweir ++pSettingNames, ++pSetting 210cdf0e10cSrcweir ) 211cdf0e10cSrcweir { 212cdf0e10cSrcweir pSetting->Name = *pSettingNames; 213cdf0e10cSrcweir pSetting->Value = xServiceSettingsNode->getByName( *pSettingNames ); 214cdf0e10cSrcweir 215cdf0e10cSrcweir if ( _pSettingTranslation ) 216cdf0e10cSrcweir (_pSettingTranslation)( _rxLogger, pSetting->Name, pSetting->Value ); 217cdf0e10cSrcweir } 218cdf0e10cSrcweir } 219cdf0e10cSrcweir 220cdf0e10cSrcweir ::rtl::OUString sServiceName; 221cdf0e10cSrcweir _rxLoggerSettings->getByName( ::rtl::OUString::createFromAscii( _pServiceNameAsciiNodeName ) ) >>= sServiceName; 222cdf0e10cSrcweir if ( sServiceName.getLength() ) 223cdf0e10cSrcweir { 224cdf0e10cSrcweir bool bSuccess = false; 225cdf0e10cSrcweir if ( aSettings.getLength() ) 226cdf0e10cSrcweir { 227cdf0e10cSrcweir Sequence< Any > aConstructionArgs(1); 228cdf0e10cSrcweir aConstructionArgs[0] <<= aSettings; 229cdf0e10cSrcweir bSuccess = _rContext.createComponentWithArguments( sServiceName, aConstructionArgs, xInstance ); 230cdf0e10cSrcweir } 231cdf0e10cSrcweir else 232cdf0e10cSrcweir { 233cdf0e10cSrcweir bSuccess = _rContext.createComponent( sServiceName, xInstance ); 234cdf0e10cSrcweir } 235cdf0e10cSrcweir 236cdf0e10cSrcweir if ( !bSuccess ) 237cdf0e10cSrcweir throw ServiceNotRegisteredException( sServiceName, NULL ); 238cdf0e10cSrcweir } 239cdf0e10cSrcweir 240cdf0e10cSrcweir return xInstance; 241cdf0e10cSrcweir } 242cdf0e10cSrcweir } 243cdf0e10cSrcweir 244cdf0e10cSrcweir //-------------------------------------------------------------------- initializeLoggerFromConfiguration(const::comphelper::ComponentContext & _rContext,const Reference<XLogger> & _rxLogger)245cdf0e10cSrcweir void initializeLoggerFromConfiguration( const ::comphelper::ComponentContext& _rContext, const Reference< XLogger >& _rxLogger ) 246cdf0e10cSrcweir { 247cdf0e10cSrcweir try 248cdf0e10cSrcweir { 249cdf0e10cSrcweir if ( !_rxLogger.is() ) 250cdf0e10cSrcweir throw NullPointerException(); 251cdf0e10cSrcweir 252cdf0e10cSrcweir // the configuration provider 253cdf0e10cSrcweir Reference< XMultiServiceFactory > xConfigProvider; 254cdf0e10cSrcweir ::rtl::OUString sConfigProvServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) ); 255cdf0e10cSrcweir if ( !_rContext.createComponent( sConfigProvServiceName, xConfigProvider ) ) 256cdf0e10cSrcweir throw ServiceNotRegisteredException( sConfigProvServiceName, _rxLogger ); 257cdf0e10cSrcweir 258cdf0e10cSrcweir // write access to the "Settings" node (which includes settings for all loggers) 259cdf0e10cSrcweir Sequence< Any > aArguments(1); 260cdf0e10cSrcweir aArguments[0] <<= NamedValue( 261cdf0e10cSrcweir ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) ), 262cdf0e10cSrcweir makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Logging/Settings" ) ) ) 263cdf0e10cSrcweir ); 264cdf0e10cSrcweir Reference< XNameContainer > xAllSettings( xConfigProvider->createInstanceWithArguments( 265cdf0e10cSrcweir ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ), 266cdf0e10cSrcweir aArguments 267cdf0e10cSrcweir ), UNO_QUERY_THROW ); 268cdf0e10cSrcweir 269cdf0e10cSrcweir ::rtl::OUString sLoggerName( _rxLogger->getName() ); 270cdf0e10cSrcweir if ( !xAllSettings->hasByName( sLoggerName ) ) 271cdf0e10cSrcweir { 272cdf0e10cSrcweir // no node yet for this logger. Create default settings. 273cdf0e10cSrcweir Reference< XSingleServiceFactory > xNodeFactory( xAllSettings, UNO_QUERY_THROW ); 274cdf0e10cSrcweir Reference< XInterface > xLoggerSettings( xNodeFactory->createInstance(), UNO_QUERY_THROW ); 275cdf0e10cSrcweir xAllSettings->insertByName( sLoggerName, makeAny( xLoggerSettings ) ); 276cdf0e10cSrcweir Reference< XChangesBatch > xChanges( xAllSettings, UNO_QUERY_THROW ); 277cdf0e10cSrcweir xChanges->commitChanges(); 278cdf0e10cSrcweir } 279cdf0e10cSrcweir 280cdf0e10cSrcweir // actually read and forward the settings 281cdf0e10cSrcweir Reference< XNameAccess > xLoggerSettings( xAllSettings->getByName( sLoggerName ), UNO_QUERY_THROW ); 282cdf0e10cSrcweir 283cdf0e10cSrcweir // the log level 284cdf0e10cSrcweir sal_Int32 nLogLevel( LogLevel::OFF ); 285cdf0e10cSrcweir OSL_VERIFY( xLoggerSettings->getByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LogLevel" ) ) ) >>= nLogLevel ); 286cdf0e10cSrcweir _rxLogger->setLevel( nLogLevel ); 287cdf0e10cSrcweir 288cdf0e10cSrcweir // the default handler, if any 289cdf0e10cSrcweir Reference< XInterface > xUntyped( lcl_createInstanceFromSetting_throw( _rContext, _rxLogger, xLoggerSettings, "DefaultHandler", "HandlerSettings", &lcl_transformFileHandlerSettings_nothrow ) ); 290cdf0e10cSrcweir if ( !xUntyped.is() ) 291cdf0e10cSrcweir // no handler -> we're done 292cdf0e10cSrcweir return; 293cdf0e10cSrcweir Reference< XLogHandler > xHandler( xUntyped, UNO_QUERY_THROW ); 294cdf0e10cSrcweir _rxLogger->addLogHandler( xHandler ); 295cdf0e10cSrcweir 296cdf0e10cSrcweir // The newly created handler might have an own (default) level. Ensure that it uses 297cdf0e10cSrcweir // the same level as the logger. 298cdf0e10cSrcweir xHandler->setLevel( nLogLevel ); 299cdf0e10cSrcweir 300cdf0e10cSrcweir // the default formatter for the handler 301cdf0e10cSrcweir xUntyped = lcl_createInstanceFromSetting_throw( _rContext, _rxLogger, xLoggerSettings, "DefaultFormatter", "FormatterSettings" ); 302cdf0e10cSrcweir if ( !xUntyped.is() ) 303cdf0e10cSrcweir // no formatter -> we're done 304cdf0e10cSrcweir return; 305cdf0e10cSrcweir Reference< XLogFormatter > xFormatter( xUntyped, UNO_QUERY_THROW ); 306cdf0e10cSrcweir xHandler->setFormatter( xFormatter ); 307cdf0e10cSrcweir 308cdf0e10cSrcweir // TODO: we could first create the formatter, then the handler. This would allow 309cdf0e10cSrcweir // passing the formatter as value in the component context, so the handler would 310cdf0e10cSrcweir // not create an own default formatter 311cdf0e10cSrcweir } 312cdf0e10cSrcweir catch( const Exception& ) 313cdf0e10cSrcweir { 314cdf0e10cSrcweir DBG_UNHANDLED_EXCEPTION(); 315cdf0e10cSrcweir } 316cdf0e10cSrcweir } 317cdf0e10cSrcweir 318cdf0e10cSrcweir //........................................................................ 319cdf0e10cSrcweir } // namespace logging 320cdf0e10cSrcweir //........................................................................ 321