1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: loggerconfig.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_extensions.hxx"
34 #include "loggerconfig.hxx"
36 /** === begin UNO includes === **/
37 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
38 #include <com/sun/star/container/XNameContainer.hpp>
39 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
40 #include <com/sun/star/util/XChangesBatch.hpp>
41 #include <com/sun/star/logging/LogLevel.hpp>
42 #include <com/sun/star/lang/NullPointerException.hpp>
43 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
44 #include <com/sun/star/beans/NamedValue.hpp>
45 #include <com/sun/star/logging/XLogHandler.hpp>
46 #include <com/sun/star/logging/XLogFormatter.hpp>
47 /** === end UNO includes === **/
49 #include <tools/diagnose_ex.h>
51 #include <comphelper/componentcontext.hxx>
53 #include <cppuhelper/component_context.hxx>
57 //........................................................................
60 //........................................................................
62 /** === begin UNO using === **/
63 using ::com::sun::star::uno::Reference
;
64 using ::com::sun::star::logging::XLogger
;
65 using ::com::sun::star::lang::XMultiServiceFactory
;
66 using ::com::sun::star::uno::Sequence
;
67 using ::com::sun::star::uno::Any
;
68 using ::com::sun::star::container::XNameContainer
;
69 using ::com::sun::star::uno::UNO_QUERY_THROW
;
70 using ::com::sun::star::lang::XSingleServiceFactory
;
71 using ::com::sun::star::uno::XInterface
;
72 using ::com::sun::star::util::XChangesBatch
;
73 using ::com::sun::star::uno::makeAny
;
74 using ::com::sun::star::lang::NullPointerException
;
75 using ::com::sun::star::uno::Exception
;
76 using ::com::sun::star::lang::ServiceNotRegisteredException
;
77 using ::com::sun::star::beans::NamedValue
;
78 using ::com::sun::star::logging::XLogHandler
;
79 using ::com::sun::star::logging::XLogFormatter
;
80 using ::com::sun::star::container::XNameAccess
;
81 using ::com::sun::star::uno::XComponentContext
;
82 /** === end UNO using === **/
83 namespace LogLevel
= ::com::sun::star::logging::LogLevel
;
87 //----------------------------------------------------------------
88 typedef void (*SettingTranslation
)( const Reference
< XLogger
>&, const ::rtl::OUString
&, Any
& );
90 //----------------------------------------------------------------
91 void lcl_substituteFileHandlerURLVariables_nothrow( const Reference
< XLogger
>& _rxLogger
, ::rtl::OUString
& _inout_rFileURL
)
95 const sal_Char
* pVariablePattern
;
96 const sal_Int32 nPatternLength
;
97 rtl_TextEncoding eEncoding
;
98 const ::rtl::OUString sVariableValue
;
100 Variable( const sal_Char
* _pVariablePattern
, const sal_Int32 _nPatternLength
, rtl_TextEncoding _eEncoding
,
101 const ::rtl::OUString
& _rVariableValue
)
102 :pVariablePattern( _pVariablePattern
)
103 ,nPatternLength( _nPatternLength
)
104 ,eEncoding( _eEncoding
)
105 ,sVariableValue( _rVariableValue
)
110 ::rtl::OUString sLoggerName
;
111 try { sLoggerName
= _rxLogger
->getName(); }
112 catch( const Exception
& ) { DBG_UNHANDLED_EXCEPTION(); }
114 Variable aVariables
[] =
116 Variable( RTL_CONSTASCII_USTRINGPARAM( "$(loggername)" ), sLoggerName
)
119 for ( size_t i
= 0; i
< sizeof( aVariables
) / sizeof( aVariables
[0] ); ++i
)
121 ::rtl::OUString
sPattern( aVariables
[i
].pVariablePattern
, aVariables
[i
].nPatternLength
, aVariables
[i
].eEncoding
);
122 sal_Int32 nVariableIndex
= _inout_rFileURL
.indexOf( sPattern
);
123 if ( ( nVariableIndex
== 0 )
124 || ( ( nVariableIndex
> 0 )
125 && ( sPattern
[ nVariableIndex
- 1 ] != '$' )
129 // found an (unescaped) variable
130 _inout_rFileURL
= _inout_rFileURL
.replaceAt( nVariableIndex
, sPattern
.getLength(), aVariables
[i
].sVariableValue
);
135 //----------------------------------------------------------------
136 void lcl_transformFileHandlerSettings_nothrow( const Reference
< XLogger
>& _rxLogger
, const ::rtl::OUString
& _rSettingName
, Any
& _inout_rSettingValue
)
138 if ( !_rSettingName
.equalsAscii( "FileURL" ) )
139 // not interested in this setting
142 ::rtl::OUString sURL
;
143 OSL_VERIFY( _inout_rSettingValue
>>= sURL
);
144 lcl_substituteFileHandlerURLVariables_nothrow( _rxLogger
, sURL
);
145 _inout_rSettingValue
<<= sURL
;
148 //----------------------------------------------------------------
149 Reference
< XInterface
> lcl_createInstanceFromSetting_throw(
150 const ::comphelper::ComponentContext
& _rContext
,
151 const Reference
< XLogger
>& _rxLogger
,
152 const Reference
< XNameAccess
>& _rxLoggerSettings
,
153 const sal_Char
* _pServiceNameAsciiNodeName
,
154 const sal_Char
* _pServiceSettingsAsciiNodeName
,
155 SettingTranslation _pSettingTranslation
= NULL
158 Reference
< XInterface
> xInstance
;
160 // read the settings for the to-be-created service
161 Reference
< XNameAccess
> xServiceSettingsNode( _rxLoggerSettings
->getByName(
162 ::rtl::OUString::createFromAscii( _pServiceSettingsAsciiNodeName
) ), UNO_QUERY_THROW
);
164 Sequence
< ::rtl::OUString
> aSettingNames( xServiceSettingsNode
->getElementNames() );
165 size_t nServiceSettingCount( aSettingNames
.getLength() );
166 Sequence
< NamedValue
> aSettings( nServiceSettingCount
);
167 if ( nServiceSettingCount
)
169 const ::rtl::OUString
* pSettingNames
= aSettingNames
.getConstArray();
170 const ::rtl::OUString
* pSettingNamesEnd
= aSettingNames
.getConstArray() + aSettingNames
.getLength();
171 NamedValue
* pSetting
= aSettings
.getArray();
174 pSettingNames
!= pSettingNamesEnd
;
175 ++pSettingNames
, ++pSetting
178 pSetting
->Name
= *pSettingNames
;
179 pSetting
->Value
= xServiceSettingsNode
->getByName( *pSettingNames
);
181 if ( _pSettingTranslation
)
182 (_pSettingTranslation
)( _rxLogger
, pSetting
->Name
, pSetting
->Value
);
186 ::rtl::OUString sServiceName
;
187 _rxLoggerSettings
->getByName( ::rtl::OUString::createFromAscii( _pServiceNameAsciiNodeName
) ) >>= sServiceName
;
188 if ( sServiceName
.getLength() )
190 bool bSuccess
= false;
191 if ( aSettings
.getLength() )
193 Sequence
< Any
> aConstructionArgs(1);
194 aConstructionArgs
[0] <<= aSettings
;
195 bSuccess
= _rContext
.createComponentWithArguments( sServiceName
, aConstructionArgs
, xInstance
);
199 bSuccess
= _rContext
.createComponent( sServiceName
, xInstance
);
203 throw ServiceNotRegisteredException( sServiceName
, NULL
);
210 //--------------------------------------------------------------------
211 void initializeLoggerFromConfiguration( const ::comphelper::ComponentContext
& _rContext
, const Reference
< XLogger
>& _rxLogger
)
215 if ( !_rxLogger
.is() )
216 throw NullPointerException();
218 // the configuration provider
219 Reference
< XMultiServiceFactory
> xConfigProvider
;
220 ::rtl::OUString
sConfigProvServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) );
221 if ( !_rContext
.createComponent( sConfigProvServiceName
, xConfigProvider
) )
222 throw ServiceNotRegisteredException( sConfigProvServiceName
, _rxLogger
);
224 // write access to the "Settings" node (which includes settings for all loggers)
225 Sequence
< Any
> aArguments(1);
226 aArguments
[0] <<= NamedValue(
227 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) ),
228 makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Logging/Settings" ) ) )
230 Reference
< XNameContainer
> xAllSettings( xConfigProvider
->createInstanceWithArguments(
231 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ),
233 ), UNO_QUERY_THROW
);
235 ::rtl::OUString
sLoggerName( _rxLogger
->getName() );
236 if ( !xAllSettings
->hasByName( sLoggerName
) )
238 // no node yet for this logger. Create default settings.
239 Reference
< XSingleServiceFactory
> xNodeFactory( xAllSettings
, UNO_QUERY_THROW
);
240 Reference
< XInterface
> xLoggerSettings( xNodeFactory
->createInstance(), UNO_QUERY_THROW
);
241 xAllSettings
->insertByName( sLoggerName
, makeAny( xLoggerSettings
) );
242 Reference
< XChangesBatch
> xChanges( xAllSettings
, UNO_QUERY_THROW
);
243 xChanges
->commitChanges();
246 // actually read and forward the settings
247 Reference
< XNameAccess
> xLoggerSettings( xAllSettings
->getByName( sLoggerName
), UNO_QUERY_THROW
);
250 sal_Int32
nLogLevel( LogLevel::OFF
);
251 OSL_VERIFY( xLoggerSettings
->getByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LogLevel" ) ) ) >>= nLogLevel
);
252 _rxLogger
->setLevel( nLogLevel
);
254 // the default handler, if any
255 Reference
< XInterface
> xUntyped( lcl_createInstanceFromSetting_throw( _rContext
, _rxLogger
, xLoggerSettings
, "DefaultHandler", "HandlerSettings", &lcl_transformFileHandlerSettings_nothrow
) );
256 if ( !xUntyped
.is() )
257 // no handler -> we're done
259 Reference
< XLogHandler
> xHandler( xUntyped
, UNO_QUERY_THROW
);
260 _rxLogger
->addLogHandler( xHandler
);
262 // The newly created handler might have an own (default) level. Ensure that it uses
263 // the same level as the logger.
264 xHandler
->setLevel( nLogLevel
);
266 // the default formatter for the handler
267 xUntyped
= lcl_createInstanceFromSetting_throw( _rContext
, _rxLogger
, xLoggerSettings
, "DefaultFormatter", "FormatterSettings" );
268 if ( !xUntyped
.is() )
269 // no formatter -> we're done
271 Reference
< XLogFormatter
> xFormatter( xUntyped
, UNO_QUERY_THROW
);
272 xHandler
->setFormatter( xFormatter
);
274 // TODO: we could first create the formatter, then the handler. This would allow
275 // passing the formatter as value in the component context, so the handler would
276 // not create an own default formatter
278 catch( const Exception
& )
280 DBG_UNHANDLED_EXCEPTION();
284 //........................................................................
285 } // namespace logging
286 //........................................................................