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