1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
31 #include "loggerconfig.hxx"
33 /** === begin UNO includes === **/
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <com/sun/star/container/XNameContainer.hpp>
36 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
37 #include <com/sun/star/util/XChangesBatch.hpp>
38 #include <com/sun/star/logging/LogLevel.hpp>
39 #include <com/sun/star/lang/NullPointerException.hpp>
40 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
41 #include <com/sun/star/beans/NamedValue.hpp>
42 #include <com/sun/star/logging/XLogHandler.hpp>
43 #include <com/sun/star/logging/XLogFormatter.hpp>
44 /** === end UNO includes === **/
46 #include <tools/diagnose_ex.h>
48 #include <comphelper/componentcontext.hxx>
50 #include <cppuhelper/component_context.hxx>
54 //........................................................................
57 //........................................................................
59 /** === begin UNO using === **/
60 using ::com::sun::star::uno::Reference
;
61 using ::com::sun::star::logging::XLogger
;
62 using ::com::sun::star::lang::XMultiServiceFactory
;
63 using ::com::sun::star::uno::Sequence
;
64 using ::com::sun::star::uno::Any
;
65 using ::com::sun::star::container::XNameContainer
;
66 using ::com::sun::star::uno::UNO_QUERY_THROW
;
67 using ::com::sun::star::lang::XSingleServiceFactory
;
68 using ::com::sun::star::uno::XInterface
;
69 using ::com::sun::star::util::XChangesBatch
;
70 using ::com::sun::star::uno::makeAny
;
71 using ::com::sun::star::lang::NullPointerException
;
72 using ::com::sun::star::uno::Exception
;
73 using ::com::sun::star::lang::ServiceNotRegisteredException
;
74 using ::com::sun::star::beans::NamedValue
;
75 using ::com::sun::star::logging::XLogHandler
;
76 using ::com::sun::star::logging::XLogFormatter
;
77 using ::com::sun::star::container::XNameAccess
;
78 using ::com::sun::star::uno::XComponentContext
;
79 /** === end UNO using === **/
80 namespace LogLevel
= ::com::sun::star::logging::LogLevel
;
84 //----------------------------------------------------------------
85 typedef void (*SettingTranslation
)( const Reference
< XLogger
>&, const ::rtl::OUString
&, Any
& );
87 //----------------------------------------------------------------
88 void lcl_substituteFileHandlerURLVariables_nothrow( const Reference
< XLogger
>& _rxLogger
, ::rtl::OUString
& _inout_rFileURL
)
92 const sal_Char
* pVariablePattern
;
93 const sal_Int32 nPatternLength
;
94 rtl_TextEncoding eEncoding
;
95 const ::rtl::OUString sVariableValue
;
97 Variable( const sal_Char
* _pVariablePattern
, const sal_Int32 _nPatternLength
, rtl_TextEncoding _eEncoding
,
98 const ::rtl::OUString
& _rVariableValue
)
99 :pVariablePattern( _pVariablePattern
)
100 ,nPatternLength( _nPatternLength
)
101 ,eEncoding( _eEncoding
)
102 ,sVariableValue( _rVariableValue
)
107 ::rtl::OUString sLoggerName
;
108 try { sLoggerName
= _rxLogger
->getName(); }
109 catch( const Exception
& ) { DBG_UNHANDLED_EXCEPTION(); }
111 Variable aVariables
[] =
113 Variable( RTL_CONSTASCII_USTRINGPARAM( "$(loggername)" ), sLoggerName
)
116 for ( size_t i
= 0; i
< sizeof( aVariables
) / sizeof( aVariables
[0] ); ++i
)
118 ::rtl::OUString
sPattern( aVariables
[i
].pVariablePattern
, aVariables
[i
].nPatternLength
, aVariables
[i
].eEncoding
);
119 sal_Int32 nVariableIndex
= _inout_rFileURL
.indexOf( sPattern
);
120 if ( ( nVariableIndex
== 0 )
121 || ( ( nVariableIndex
> 0 )
122 && ( sPattern
[ nVariableIndex
- 1 ] != '$' )
126 // found an (unescaped) variable
127 _inout_rFileURL
= _inout_rFileURL
.replaceAt( nVariableIndex
, sPattern
.getLength(), aVariables
[i
].sVariableValue
);
132 //----------------------------------------------------------------
133 void lcl_transformFileHandlerSettings_nothrow( const Reference
< XLogger
>& _rxLogger
, const ::rtl::OUString
& _rSettingName
, Any
& _inout_rSettingValue
)
135 if ( !_rSettingName
.equalsAscii( "FileURL" ) )
136 // not interested in this setting
139 ::rtl::OUString sURL
;
140 OSL_VERIFY( _inout_rSettingValue
>>= sURL
);
141 lcl_substituteFileHandlerURLVariables_nothrow( _rxLogger
, sURL
);
142 _inout_rSettingValue
<<= sURL
;
145 //----------------------------------------------------------------
146 Reference
< XInterface
> lcl_createInstanceFromSetting_throw(
147 const ::comphelper::ComponentContext
& _rContext
,
148 const Reference
< XLogger
>& _rxLogger
,
149 const Reference
< XNameAccess
>& _rxLoggerSettings
,
150 const sal_Char
* _pServiceNameAsciiNodeName
,
151 const sal_Char
* _pServiceSettingsAsciiNodeName
,
152 SettingTranslation _pSettingTranslation
= NULL
155 Reference
< XInterface
> xInstance
;
157 // read the settings for the to-be-created service
158 Reference
< XNameAccess
> xServiceSettingsNode( _rxLoggerSettings
->getByName(
159 ::rtl::OUString::createFromAscii( _pServiceSettingsAsciiNodeName
) ), UNO_QUERY_THROW
);
161 Sequence
< ::rtl::OUString
> aSettingNames( xServiceSettingsNode
->getElementNames() );
162 size_t nServiceSettingCount( aSettingNames
.getLength() );
163 Sequence
< NamedValue
> aSettings( nServiceSettingCount
);
164 if ( nServiceSettingCount
)
166 const ::rtl::OUString
* pSettingNames
= aSettingNames
.getConstArray();
167 const ::rtl::OUString
* pSettingNamesEnd
= aSettingNames
.getConstArray() + aSettingNames
.getLength();
168 NamedValue
* pSetting
= aSettings
.getArray();
171 pSettingNames
!= pSettingNamesEnd
;
172 ++pSettingNames
, ++pSetting
175 pSetting
->Name
= *pSettingNames
;
176 pSetting
->Value
= xServiceSettingsNode
->getByName( *pSettingNames
);
178 if ( _pSettingTranslation
)
179 (_pSettingTranslation
)( _rxLogger
, pSetting
->Name
, pSetting
->Value
);
183 ::rtl::OUString sServiceName
;
184 _rxLoggerSettings
->getByName( ::rtl::OUString::createFromAscii( _pServiceNameAsciiNodeName
) ) >>= sServiceName
;
185 if ( sServiceName
.getLength() )
187 bool bSuccess
= false;
188 if ( aSettings
.getLength() )
190 Sequence
< Any
> aConstructionArgs(1);
191 aConstructionArgs
[0] <<= aSettings
;
192 bSuccess
= _rContext
.createComponentWithArguments( sServiceName
, aConstructionArgs
, xInstance
);
196 bSuccess
= _rContext
.createComponent( sServiceName
, xInstance
);
200 throw ServiceNotRegisteredException( sServiceName
, NULL
);
207 //--------------------------------------------------------------------
208 void initializeLoggerFromConfiguration( const ::comphelper::ComponentContext
& _rContext
, const Reference
< XLogger
>& _rxLogger
)
212 if ( !_rxLogger
.is() )
213 throw NullPointerException();
215 // the configuration provider
216 Reference
< XMultiServiceFactory
> xConfigProvider
;
217 ::rtl::OUString
sConfigProvServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) );
218 if ( !_rContext
.createComponent( sConfigProvServiceName
, xConfigProvider
) )
219 throw ServiceNotRegisteredException( sConfigProvServiceName
, _rxLogger
);
221 // write access to the "Settings" node (which includes settings for all loggers)
222 Sequence
< Any
> aArguments(1);
223 aArguments
[0] <<= NamedValue(
224 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) ),
225 makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Logging/Settings" ) ) )
227 Reference
< XNameContainer
> xAllSettings( xConfigProvider
->createInstanceWithArguments(
228 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ),
230 ), UNO_QUERY_THROW
);
232 ::rtl::OUString
sLoggerName( _rxLogger
->getName() );
233 if ( !xAllSettings
->hasByName( sLoggerName
) )
235 // no node yet for this logger. Create default settings.
236 Reference
< XSingleServiceFactory
> xNodeFactory( xAllSettings
, UNO_QUERY_THROW
);
237 Reference
< XInterface
> xLoggerSettings( xNodeFactory
->createInstance(), UNO_QUERY_THROW
);
238 xAllSettings
->insertByName( sLoggerName
, makeAny( xLoggerSettings
) );
239 Reference
< XChangesBatch
> xChanges( xAllSettings
, UNO_QUERY_THROW
);
240 xChanges
->commitChanges();
243 // actually read and forward the settings
244 Reference
< XNameAccess
> xLoggerSettings( xAllSettings
->getByName( sLoggerName
), UNO_QUERY_THROW
);
247 sal_Int32
nLogLevel( LogLevel::OFF
);
248 OSL_VERIFY( xLoggerSettings
->getByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LogLevel" ) ) ) >>= nLogLevel
);
249 _rxLogger
->setLevel( nLogLevel
);
251 // the default handler, if any
252 Reference
< XInterface
> xUntyped( lcl_createInstanceFromSetting_throw( _rContext
, _rxLogger
, xLoggerSettings
, "DefaultHandler", "HandlerSettings", &lcl_transformFileHandlerSettings_nothrow
) );
253 if ( !xUntyped
.is() )
254 // no handler -> we're done
256 Reference
< XLogHandler
> xHandler( xUntyped
, UNO_QUERY_THROW
);
257 _rxLogger
->addLogHandler( xHandler
);
259 // The newly created handler might have an own (default) level. Ensure that it uses
260 // the same level as the logger.
261 xHandler
->setLevel( nLogLevel
);
263 // the default formatter for the handler
264 xUntyped
= lcl_createInstanceFromSetting_throw( _rContext
, _rxLogger
, xLoggerSettings
, "DefaultFormatter", "FormatterSettings" );
265 if ( !xUntyped
.is() )
266 // no formatter -> we're done
268 Reference
< XLogFormatter
> xFormatter( xUntyped
, UNO_QUERY_THROW
);
269 xHandler
->setFormatter( xFormatter
);
271 // TODO: we could first create the formatter, then the handler. This would allow
272 // passing the formatter as value in the component context, so the handler would
273 // not create an own default formatter
275 catch( const Exception
& )
277 DBG_UNHANDLED_EXCEPTION();
281 //........................................................................
282 } // namespace logging
283 //........................................................................