1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_comphelper.hxx" 26 27 #include <comphelper/logging.hxx> 28 #include <comphelper/componentcontext.hxx> 29 30 /** === begin UNO includes === **/ 31 #include <com/sun/star/logging/LoggerPool.hpp> 32 #include <com/sun/star/logging/LogLevel.hpp> 33 #include <com/sun/star/resource/XResourceBundle.hpp> 34 #include <com/sun/star/resource/XResourceBundleLoader.hpp> 35 /** === end UNO includes === **/ 36 37 #include <rtl/ustrbuf.hxx> 38 39 //........................................................................ 40 namespace comphelper 41 { 42 //........................................................................ 43 44 /** === begin UNO using === **/ 45 using ::com::sun::star::uno::Reference; 46 using ::com::sun::star::uno::XComponentContext; 47 using ::com::sun::star::logging::XLoggerPool; 48 using ::com::sun::star::logging::LoggerPool; 49 using ::com::sun::star::logging::XLogger; 50 using ::com::sun::star::uno::UNO_QUERY_THROW; 51 using ::com::sun::star::uno::Exception; 52 using ::com::sun::star::logging::XLogHandler; 53 using ::com::sun::star::resource::XResourceBundle; 54 using ::com::sun::star::resource::XResourceBundleLoader; 55 /** === end UNO using === **/ 56 namespace LogLevel = ::com::sun::star::logging::LogLevel; 57 58 //==================================================================== 59 //= EventLogger_Impl - declaration 60 //==================================================================== 61 class EventLogger_Impl 62 { 63 private: 64 ::comphelper::ComponentContext m_aContext; 65 ::rtl::OUString m_sLoggerName; 66 Reference< XLogger > m_xLogger; 67 68 public: EventLogger_Impl(const Reference<XComponentContext> & _rxContext,const::rtl::OUString & _rLoggerName)69 EventLogger_Impl( const Reference< XComponentContext >& _rxContext, const ::rtl::OUString& _rLoggerName ) 70 :m_aContext( _rxContext ) 71 ,m_sLoggerName( _rLoggerName ) 72 { 73 impl_createLogger_nothrow(); 74 } 75 isValid() const76 inline bool isValid() const { return m_xLogger.is(); } getName() const77 inline const ::rtl::OUString& getName() const { return m_sLoggerName; } getLogger() const78 inline const Reference< XLogger >& getLogger() const { return m_xLogger; } getContext() const79 inline const ::comphelper::ComponentContext& getContext() const { return m_aContext; } 80 81 private: 82 void impl_createLogger_nothrow(); 83 }; 84 85 //==================================================================== 86 //= EventLogger_Impl - implementation 87 //==================================================================== 88 //-------------------------------------------------------------------- impl_createLogger_nothrow()89 void EventLogger_Impl::impl_createLogger_nothrow() 90 { 91 try 92 { 93 Reference< XLoggerPool > xPool( LoggerPool::get( m_aContext.getUNOContext() ), UNO_QUERY_THROW ); 94 if ( !m_sLoggerName.isEmpty() ) 95 m_xLogger = xPool->getNamedLogger( m_sLoggerName ); 96 else 97 m_xLogger = xPool->getDefaultLogger(); 98 } 99 catch( const Exception& e ) 100 { 101 (void)e; 102 OSL_ENSURE( false, "EventLogger_Impl::impl_createLogger_nothrow: caught an exception!" ); 103 } 104 } 105 106 //==================================================================== 107 //= EventLogger 108 //==================================================================== 109 //-------------------------------------------------------------------- EventLogger(const Reference<XComponentContext> & _rxContext,const::rtl::OUString & _rLoggerName)110 EventLogger::EventLogger( const Reference< XComponentContext >& _rxContext, const ::rtl::OUString& _rLoggerName ) 111 :m_pImpl( new EventLogger_Impl( _rxContext, _rLoggerName ) ) 112 { 113 } 114 115 //-------------------------------------------------------------------- EventLogger(const Reference<XComponentContext> & _rxContext,const sal_Char * _pAsciiLoggerName)116 EventLogger::EventLogger( const Reference< XComponentContext >& _rxContext, const sal_Char* _pAsciiLoggerName ) 117 :m_pImpl( new EventLogger_Impl( _rxContext, ::rtl::OUString::createFromAscii( _pAsciiLoggerName ) ) ) 118 { 119 } 120 121 //-------------------------------------------------------------------- ~EventLogger()122 EventLogger::~EventLogger() 123 { 124 } 125 126 //-------------------------------------------------------------------- getName() const127 const ::rtl::OUString& EventLogger::getName() const 128 { 129 return m_pImpl->getName(); 130 } 131 132 //-------------------------------------------------------------------- getLogLevel() const133 sal_Int32 EventLogger::getLogLevel() const 134 { 135 try 136 { 137 if ( m_pImpl->isValid() ) 138 return m_pImpl->getLogger()->getLevel(); 139 } 140 catch( const Exception& e ) 141 { 142 (void)e; 143 OSL_ENSURE( false, "EventLogger::getLogLevel: caught an exception!" ); 144 } 145 146 return LogLevel::OFF; 147 } 148 149 //-------------------------------------------------------------------- setLogLevel(const sal_Int32 _nLogLevel) const150 void EventLogger::setLogLevel( const sal_Int32 _nLogLevel ) const 151 { 152 try 153 { 154 if ( m_pImpl->isValid() ) 155 m_pImpl->getLogger()->setLevel( _nLogLevel ); 156 } 157 catch( const Exception& e ) 158 { 159 (void)e; 160 OSL_ENSURE( false, "EventLogger::setLogLevel: caught an exception!" ); 161 } 162 } 163 164 //-------------------------------------------------------------------- isLoggable(const sal_Int32 _nLogLevel) const165 bool EventLogger::isLoggable( const sal_Int32 _nLogLevel ) const 166 { 167 if ( !m_pImpl->isValid() ) 168 return false; 169 170 try 171 { 172 return m_pImpl->getLogger()->isLoggable( _nLogLevel ); 173 } 174 catch( const Exception& e ) 175 { 176 (void)e; 177 OSL_ENSURE( false, "EventLogger::isLoggable: caught an exception!" ); 178 } 179 180 return false; 181 } 182 183 //-------------------------------------------------------------------- addLogHandler(const Reference<XLogHandler> & _rxLogHandler)184 bool EventLogger::addLogHandler( const Reference< XLogHandler >& _rxLogHandler ) 185 { 186 try 187 { 188 if ( m_pImpl->isValid() ) 189 { 190 m_pImpl->getLogger()->addLogHandler( _rxLogHandler ); 191 return true; 192 } 193 } 194 catch( const Exception& e ) 195 { 196 (void)e; 197 OSL_ENSURE( false, "EventLogger::addLogHandler: caught an exception!" ); 198 } 199 return false; 200 } 201 202 //-------------------------------------------------------------------- removeLogHandler(const Reference<XLogHandler> & _rxLogHandler)203 bool EventLogger::removeLogHandler( const Reference< XLogHandler >& _rxLogHandler ) 204 { 205 try 206 { 207 if ( m_pImpl->isValid() ) 208 { 209 m_pImpl->getLogger()->removeLogHandler( _rxLogHandler ); 210 return true; 211 } 212 } 213 catch( const Exception& e ) 214 { 215 (void)e; 216 OSL_ENSURE( false, "EventLogger::removeLogHandler: caught an exception!" ); 217 } 218 return false; 219 } 220 221 //-------------------------------------------------------------------- 222 namespace 223 { lcl_replaceParameter(::rtl::OUString & _inout_Message,const::rtl::OUString & _rPlaceHolder,const::rtl::OUString & _rReplacement)224 void lcl_replaceParameter( ::rtl::OUString& _inout_Message, const ::rtl::OUString& _rPlaceHolder, const ::rtl::OUString& _rReplacement ) 225 { 226 sal_Int32 nPlaceholderPosition = _inout_Message.indexOf( _rPlaceHolder ); 227 OSL_ENSURE( nPlaceholderPosition >= 0, "lcl_replaceParameter: placeholder not found!" ); 228 if ( nPlaceholderPosition < 0 ) 229 return; 230 231 _inout_Message = _inout_Message.replaceAt( nPlaceholderPosition, _rPlaceHolder.getLength(), _rReplacement ); 232 } 233 } 234 235 //-------------------------------------------------------------------- impl_log(const sal_Int32 _nLogLevel,const sal_Char * _pSourceClass,const sal_Char * _pSourceMethod,const::rtl::OUString & _rMessage,const OptionalString & _rArgument1,const OptionalString & _rArgument2,const OptionalString & _rArgument3,const OptionalString & _rArgument4,const OptionalString & _rArgument5,const OptionalString & _rArgument6) const236 bool EventLogger::impl_log( const sal_Int32 _nLogLevel, 237 const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const ::rtl::OUString& _rMessage, 238 const OptionalString& _rArgument1, const OptionalString& _rArgument2, 239 const OptionalString& _rArgument3, const OptionalString& _rArgument4, 240 const OptionalString& _rArgument5, const OptionalString& _rArgument6 ) const 241 { 242 // (if ::rtl::OUString had an indexOfAscii, we could save those ugly statics ...) 243 static ::rtl::OUString sPH1( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "$1$" ) ) ); 244 static ::rtl::OUString sPH2( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "$2$" ) ) ); 245 static ::rtl::OUString sPH3( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "$3$" ) ) ); 246 static ::rtl::OUString sPH4( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "$4$" ) ) ); 247 static ::rtl::OUString sPH5( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "$5$" ) ) ); 248 static ::rtl::OUString sPH6( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "$6$" ) ) ); 249 250 ::rtl::OUString sMessage( _rMessage ); 251 if ( !!_rArgument1 ) 252 lcl_replaceParameter( sMessage, sPH1, *_rArgument1 ); 253 254 if ( !!_rArgument2 ) 255 lcl_replaceParameter( sMessage, sPH2, *_rArgument2 ); 256 257 if ( !!_rArgument3 ) 258 lcl_replaceParameter( sMessage, sPH3, *_rArgument3 ); 259 260 if ( !!_rArgument4 ) 261 lcl_replaceParameter( sMessage, sPH4, *_rArgument4 ); 262 263 if ( !!_rArgument5 ) 264 lcl_replaceParameter( sMessage, sPH5, *_rArgument5 ); 265 266 if ( !!_rArgument6 ) 267 lcl_replaceParameter( sMessage, sPH6, *_rArgument6 ); 268 269 try 270 { 271 Reference< XLogger > xLogger( m_pImpl->getLogger() ); 272 OSL_PRECOND( xLogger.is(), "EventLogger::impl_log: should never be called without a logger!" ); 273 if ( _pSourceClass && _pSourceMethod ) 274 { 275 xLogger->logp( 276 _nLogLevel, 277 ::rtl::OUString::createFromAscii( _pSourceClass ), 278 ::rtl::OUString::createFromAscii( _pSourceMethod ), 279 sMessage 280 ); 281 } 282 else 283 { 284 xLogger->log( _nLogLevel, sMessage ); 285 } 286 } 287 catch( const Exception& e ) 288 { 289 (void)e; 290 OSL_ENSURE( false, "EventLogger::impl_log: caught an exception!" ); 291 } 292 293 return false; 294 } 295 296 //==================================================================== 297 //= ResourceBasedEventLogger_Data 298 //==================================================================== 299 struct ResourceBasedEventLogger_Data 300 { 301 /// the base name of the resource bundle 302 ::rtl::OUString sBundleBaseName; 303 /// did we already attempt to load the bundle? 304 bool bBundleLoaded; 305 /// the lazily loaded bundle 306 Reference< XResourceBundle > xBundle; 307 ResourceBasedEventLogger_Datacomphelper::ResourceBasedEventLogger_Data308 ResourceBasedEventLogger_Data() 309 :sBundleBaseName() 310 ,bBundleLoaded( false ) 311 ,xBundle() 312 { 313 } 314 }; 315 316 //-------------------------------------------------------------------- lcl_loadBundle_nothrow(const ComponentContext & _rContext,ResourceBasedEventLogger_Data & _rLoggerData)317 bool lcl_loadBundle_nothrow( const ComponentContext& _rContext, ResourceBasedEventLogger_Data& _rLoggerData ) 318 { 319 if ( _rLoggerData.bBundleLoaded ) 320 return _rLoggerData.xBundle.is(); 321 322 // no matter what happens below, don't attempt creation ever again 323 _rLoggerData.bBundleLoaded = true; 324 325 try 326 { 327 Reference< XResourceBundleLoader > xLoader( _rContext.getSingleton( "com.sun.star.resource.OfficeResourceLoader" ), UNO_QUERY_THROW ); 328 _rLoggerData.xBundle = Reference< XResourceBundle >( xLoader->loadBundle_Default( _rLoggerData.sBundleBaseName ), UNO_QUERY_THROW ); 329 } 330 catch( const Exception& e ) 331 { 332 (void)e; 333 OSL_ENSURE( false, "lcl_loadBundle_nothrow: caught an exception!" ); 334 } 335 336 return _rLoggerData.xBundle.is(); 337 } 338 339 //-------------------------------------------------------------------- lcl_loadString_nothrow(const Reference<XResourceBundle> & _rxBundle,const sal_Int32 _nMessageResID)340 ::rtl::OUString lcl_loadString_nothrow( const Reference< XResourceBundle >& _rxBundle, const sal_Int32 _nMessageResID ) 341 { 342 OSL_PRECOND( _rxBundle.is(), "lcl_loadString_nothrow: this will crash!" ); 343 ::rtl::OUString sMessage; 344 try 345 { 346 ::rtl::OUStringBuffer aBuffer; 347 aBuffer.appendAscii( "string:" ); 348 aBuffer.append( _nMessageResID ); 349 OSL_VERIFY( _rxBundle->getDirectElement( aBuffer.makeStringAndClear() ) >>= sMessage ); 350 } 351 catch( const Exception& e ) 352 { 353 (void)e; 354 OSL_ENSURE( false, "lcl_loadString_nothrow: caught an exception!" ); 355 } 356 return sMessage; 357 } 358 359 //==================================================================== 360 //= ResourceBasedEventLogger 361 //==================================================================== 362 //-------------------------------------------------------------------- ResourceBasedEventLogger(const Reference<XComponentContext> & _rxContext,const::rtl::OUString & _rResourceBundleBaseName,const::rtl::OUString & _rLoggerName)363 ResourceBasedEventLogger::ResourceBasedEventLogger( const Reference< XComponentContext >& _rxContext, const ::rtl::OUString& _rResourceBundleBaseName, 364 const ::rtl::OUString& _rLoggerName ) 365 :EventLogger( _rxContext, _rLoggerName ) 366 ,m_pData( new ResourceBasedEventLogger_Data ) 367 { 368 m_pData->sBundleBaseName = _rResourceBundleBaseName; 369 } 370 371 //-------------------------------------------------------------------- ResourceBasedEventLogger(const Reference<XComponentContext> & _rxContext,const sal_Char * _pResourceBundleBaseName,const sal_Char * _pAsciiLoggerName)372 ResourceBasedEventLogger::ResourceBasedEventLogger( const Reference< XComponentContext >& _rxContext, const sal_Char* _pResourceBundleBaseName, 373 const sal_Char* _pAsciiLoggerName ) 374 :EventLogger( _rxContext, _pAsciiLoggerName ) 375 ,m_pData( new ResourceBasedEventLogger_Data ) 376 { 377 m_pData->sBundleBaseName = ::rtl::OUString::createFromAscii( _pResourceBundleBaseName ); 378 } 379 380 //-------------------------------------------------------------------- impl_loadStringMessage_nothrow(const sal_Int32 _nMessageResID) const381 ::rtl::OUString ResourceBasedEventLogger::impl_loadStringMessage_nothrow( const sal_Int32 _nMessageResID ) const 382 { 383 ::rtl::OUString sMessage; 384 if ( lcl_loadBundle_nothrow( m_pImpl->getContext(), *m_pData ) ) 385 sMessage = lcl_loadString_nothrow( m_pData->xBundle, _nMessageResID ); 386 if ( sMessage.isEmpty() ) 387 { 388 ::rtl::OUStringBuffer aBuffer; 389 aBuffer.appendAscii( "<invalid event resource: '" ); 390 aBuffer.append( m_pData->sBundleBaseName ); 391 aBuffer.appendAscii( ":" ); 392 aBuffer.append( _nMessageResID ); 393 aBuffer.appendAscii( "'>" ); 394 sMessage = aBuffer.makeStringAndClear(); 395 } 396 return sMessage; 397 } 398 399 //........................................................................ 400 } // namespace comphelper 401 //........................................................................ 402