Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "loggerconfig.hxx"
31 : :
32 : : #include <com/sun/star/configuration/theDefaultProvider.hpp>
33 : : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34 : : #include <com/sun/star/container/XNameContainer.hpp>
35 : : #include <com/sun/star/lang/XSingleServiceFactory.hpp>
36 : : #include <com/sun/star/util/XChangesBatch.hpp>
37 : : #include <com/sun/star/logging/LogLevel.hpp>
38 : : #include <com/sun/star/lang/NullPointerException.hpp>
39 : : #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
40 : : #include <com/sun/star/beans/NamedValue.hpp>
41 : : #include <com/sun/star/logging/XLogHandler.hpp>
42 : : #include <com/sun/star/logging/XLogFormatter.hpp>
43 : :
44 : : #include <tools/diagnose_ex.h>
45 : :
46 : : #include <comphelper/componentcontext.hxx>
47 : :
48 : : #include <cppuhelper/component_context.hxx>
49 : :
50 : : #include <vector>
51 : : #include <sal/macros.h>
52 : :
53 : : //........................................................................
54 : : namespace logging
55 : : {
56 : : //........................................................................
57 : :
58 : : /** === begin UNO using === **/
59 : : using ::com::sun::star::uno::Reference;
60 : : using ::com::sun::star::logging::XLogger;
61 : : using ::com::sun::star::lang::XMultiServiceFactory;
62 : : using ::com::sun::star::uno::Sequence;
63 : : using ::com::sun::star::uno::Any;
64 : : using ::com::sun::star::container::XNameContainer;
65 : : using ::com::sun::star::uno::UNO_QUERY_THROW;
66 : : using ::com::sun::star::lang::XSingleServiceFactory;
67 : : using ::com::sun::star::uno::XInterface;
68 : : using ::com::sun::star::util::XChangesBatch;
69 : : using ::com::sun::star::uno::makeAny;
70 : : using ::com::sun::star::lang::NullPointerException;
71 : : using ::com::sun::star::uno::Exception;
72 : : using ::com::sun::star::lang::ServiceNotRegisteredException;
73 : : using ::com::sun::star::beans::NamedValue;
74 : : using ::com::sun::star::logging::XLogHandler;
75 : : using ::com::sun::star::logging::XLogFormatter;
76 : : using ::com::sun::star::container::XNameAccess;
77 : : using ::com::sun::star::uno::XComponentContext;
78 : : /** === end UNO using === **/
79 : : namespace LogLevel = ::com::sun::star::logging::LogLevel;
80 : :
81 : : namespace
82 : : {
83 : : //----------------------------------------------------------------
84 : : typedef void (*SettingTranslation)( const Reference< XLogger >&, const ::rtl::OUString&, Any& );
85 : :
86 : : //----------------------------------------------------------------
87 : 9 : void lcl_substituteFileHandlerURLVariables_nothrow( const Reference< XLogger >& _rxLogger, ::rtl::OUString& _inout_rFileURL )
88 : : {
89 : 9 : struct Variable
90 : : {
91 : : const sal_Char* pVariablePattern;
92 : : const sal_Int32 nPatternLength;
93 : : rtl_TextEncoding eEncoding;
94 : : const ::rtl::OUString sVariableValue;
95 : :
96 : 9 : Variable( const sal_Char* _pVariablePattern, const sal_Int32 _nPatternLength, rtl_TextEncoding _eEncoding,
97 : : const ::rtl::OUString& _rVariableValue )
98 : : :pVariablePattern( _pVariablePattern )
99 : : ,nPatternLength( _nPatternLength )
100 : : ,eEncoding( _eEncoding )
101 : 9 : ,sVariableValue( _rVariableValue )
102 : : {
103 : 9 : }
104 : : };
105 : :
106 : 9 : ::rtl::OUString sLoggerName;
107 [ + - ][ + - ]: 9 : try { sLoggerName = _rxLogger->getName(); }
108 [ # # ]: 0 : catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
109 : :
110 : : Variable aVariables[] =
111 : : {
112 : : Variable( RTL_CONSTASCII_USTRINGPARAM( "$(loggername)" ), sLoggerName )
113 : 18 : };
114 : :
115 [ + + ]: 18 : for ( size_t i = 0; i < SAL_N_ELEMENTS( aVariables ); ++i )
116 : : {
117 [ + - ]: 9 : ::rtl::OUString sPattern( aVariables[i].pVariablePattern, aVariables[i].nPatternLength, aVariables[i].eEncoding );
118 : 9 : sal_Int32 nVariableIndex = _inout_rFileURL.indexOf( sPattern );
119 [ + - + - ]: 18 : if ( ( nVariableIndex == 0 )
[ + - ][ + - ]
120 : : || ( ( nVariableIndex > 0 )
121 : 9 : && ( sPattern[ nVariableIndex - 1 ] != '$' )
122 : : )
123 : : )
124 : : {
125 : : // found an (unescaped) variable
126 : 9 : _inout_rFileURL = _inout_rFileURL.replaceAt( nVariableIndex, sPattern.getLength(), aVariables[i].sVariableValue );
127 : : }
128 [ + + ][ # # ]: 27 : }
129 [ # # ]: 9 : }
130 : :
131 : : //----------------------------------------------------------------
132 : 9 : void lcl_transformFileHandlerSettings_nothrow( const Reference< XLogger >& _rxLogger, const ::rtl::OUString& _rSettingName, Any& _inout_rSettingValue )
133 : : {
134 [ + - ]: 9 : if ( _rSettingName != "FileURL" )
135 : : // not interested in this setting
136 : 9 : return;
137 : :
138 : 9 : ::rtl::OUString sURL;
139 : 9 : OSL_VERIFY( _inout_rSettingValue >>= sURL );
140 [ + - ]: 9 : lcl_substituteFileHandlerURLVariables_nothrow( _rxLogger, sURL );
141 [ + - ]: 9 : _inout_rSettingValue <<= sURL;
142 : : }
143 : :
144 : : //----------------------------------------------------------------
145 : 18 : Reference< XInterface > lcl_createInstanceFromSetting_throw(
146 : : const ::comphelper::ComponentContext& _rContext,
147 : : const Reference< XLogger >& _rxLogger,
148 : : const Reference< XNameAccess >& _rxLoggerSettings,
149 : : const sal_Char* _pServiceNameAsciiNodeName,
150 : : const sal_Char* _pServiceSettingsAsciiNodeName,
151 : : SettingTranslation _pSettingTranslation = NULL
152 : : )
153 : : {
154 : 18 : Reference< XInterface > xInstance;
155 : :
156 : : // read the settings for the to-be-created service
157 [ + - ]: 18 : Reference< XNameAccess > xServiceSettingsNode( _rxLoggerSettings->getByName(
158 [ + - ][ + - ]: 18 : ::rtl::OUString::createFromAscii( _pServiceSettingsAsciiNodeName ) ), UNO_QUERY_THROW );
159 : :
160 [ + - ][ + - ]: 18 : Sequence< ::rtl::OUString > aSettingNames( xServiceSettingsNode->getElementNames() );
161 : 18 : size_t nServiceSettingCount( aSettingNames.getLength() );
162 [ + - ]: 18 : Sequence< NamedValue > aSettings( nServiceSettingCount );
163 [ + + ]: 18 : if ( nServiceSettingCount )
164 : : {
165 : 9 : const ::rtl::OUString* pSettingNames = aSettingNames.getConstArray();
166 : 9 : const ::rtl::OUString* pSettingNamesEnd = aSettingNames.getConstArray() + aSettingNames.getLength();
167 [ + - ]: 9 : NamedValue* pSetting = aSettings.getArray();
168 : :
169 [ + + ]: 18 : for ( ;
170 : : pSettingNames != pSettingNamesEnd;
171 : : ++pSettingNames, ++pSetting
172 : : )
173 : : {
174 : 9 : pSetting->Name = *pSettingNames;
175 [ + - ][ + - ]: 9 : pSetting->Value = xServiceSettingsNode->getByName( *pSettingNames );
176 : :
177 [ + - ]: 9 : if ( _pSettingTranslation )
178 [ + - ]: 9 : (_pSettingTranslation)( _rxLogger, pSetting->Name, pSetting->Value );
179 : : }
180 : : }
181 : :
182 : 18 : ::rtl::OUString sServiceName;
183 [ + - ][ + - ]: 18 : _rxLoggerSettings->getByName( ::rtl::OUString::createFromAscii( _pServiceNameAsciiNodeName ) ) >>= sServiceName;
184 [ + - ]: 18 : if ( !sServiceName.isEmpty() )
185 : : {
186 : 18 : bool bSuccess = false;
187 [ + + ]: 18 : if ( aSettings.getLength() )
188 : : {
189 [ + - ]: 9 : Sequence< Any > aConstructionArgs(1);
190 [ + - ][ + - ]: 9 : aConstructionArgs[0] <<= aSettings;
191 [ + - ][ + - ]: 9 : bSuccess = _rContext.createComponentWithArguments( sServiceName, aConstructionArgs, xInstance );
192 : : }
193 : : else
194 : : {
195 [ + - ]: 9 : bSuccess = _rContext.createComponent( sServiceName, xInstance );
196 : : }
197 : :
198 [ - + ]: 18 : if ( !bSuccess )
199 [ # # ][ # # ]: 0 : throw ServiceNotRegisteredException( sServiceName, NULL );
200 : : }
201 : :
202 [ + - ][ + - ]: 18 : return xInstance;
203 : : }
204 : : }
205 : :
206 : : //--------------------------------------------------------------------
207 : 9 : void initializeLoggerFromConfiguration( const ::comphelper::ComponentContext& _rContext, const Reference< XLogger >& _rxLogger )
208 : : {
209 : : try
210 : : {
211 [ - + ]: 9 : if ( !_rxLogger.is() )
212 [ # # ]: 0 : throw NullPointerException();
213 : :
214 : : Reference< XMultiServiceFactory > xConfigProvider(
215 : : com::sun::star::configuration::theDefaultProvider::get(
216 [ + - ][ + - ]: 9 : _rContext.getUNOContext()));
217 : :
218 : : // write access to the "Settings" node (which includes settings for all loggers)
219 [ + - ]: 9 : Sequence< Any > aArguments(1);
220 [ + - ]: 9 : aArguments[0] <<= NamedValue(
221 : : ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) ),
222 : : makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Logging/Settings" ) ) )
223 [ + - ][ + - ]: 18 : );
[ + - ][ + - ]
224 [ + - ]: 9 : Reference< XNameContainer > xAllSettings( xConfigProvider->createInstanceWithArguments(
225 : : ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ),
226 : : aArguments
227 [ + - ][ + - ]: 9 : ), UNO_QUERY_THROW );
[ + - ]
228 : :
229 [ + - ][ + - ]: 9 : ::rtl::OUString sLoggerName( _rxLogger->getName() );
230 [ + - ][ + - ]: 9 : if ( !xAllSettings->hasByName( sLoggerName ) )
[ + - ]
231 : : {
232 : : // no node yet for this logger. Create default settings.
233 [ + - ]: 9 : Reference< XSingleServiceFactory > xNodeFactory( xAllSettings, UNO_QUERY_THROW );
234 [ + - ][ + - ]: 9 : Reference< XInterface > xLoggerSettings( xNodeFactory->createInstance(), UNO_QUERY_THROW );
[ + - ]
235 [ + - ][ + - ]: 9 : xAllSettings->insertByName( sLoggerName, makeAny( xLoggerSettings ) );
[ + - ]
236 [ + - ]: 9 : Reference< XChangesBatch > xChanges( xAllSettings, UNO_QUERY_THROW );
237 [ + - ][ + - ]: 9 : xChanges->commitChanges();
238 : : }
239 : :
240 : : // actually read and forward the settings
241 [ + - ][ + - ]: 9 : Reference< XNameAccess > xLoggerSettings( xAllSettings->getByName( sLoggerName ), UNO_QUERY_THROW );
[ + - ]
242 : :
243 : : // the log level
244 : 9 : sal_Int32 nLogLevel( LogLevel::OFF );
245 [ + - ][ + - ]: 9 : OSL_VERIFY( xLoggerSettings->getByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LogLevel" ) ) ) >>= nLogLevel );
[ + - ]
246 [ + - ][ + - ]: 9 : _rxLogger->setLevel( nLogLevel );
247 : :
248 : : // the default handler, if any
249 [ + - ]: 9 : Reference< XInterface > xUntyped( lcl_createInstanceFromSetting_throw( _rContext, _rxLogger, xLoggerSettings, "DefaultHandler", "HandlerSettings", &lcl_transformFileHandlerSettings_nothrow ) );
250 [ - + ]: 9 : if ( !xUntyped.is() )
251 : : // no handler -> we're done
252 : : return;
253 [ + - ]: 9 : Reference< XLogHandler > xHandler( xUntyped, UNO_QUERY_THROW );
254 [ + - ][ + - ]: 9 : _rxLogger->addLogHandler( xHandler );
255 : :
256 : : // The newly created handler might have an own (default) level. Ensure that it uses
257 : : // the same level as the logger.
258 [ + - ][ + - ]: 9 : xHandler->setLevel( nLogLevel );
259 : :
260 : : // the default formatter for the handler
261 [ + - ][ + - ]: 9 : xUntyped = lcl_createInstanceFromSetting_throw( _rContext, _rxLogger, xLoggerSettings, "DefaultFormatter", "FormatterSettings" );
262 [ - + ]: 9 : if ( !xUntyped.is() )
263 : : // no formatter -> we're done
264 : : return;
265 [ + - ]: 9 : Reference< XLogFormatter > xFormatter( xUntyped, UNO_QUERY_THROW );
266 [ + - ][ + - ]: 9 : xHandler->setFormatter( xFormatter );
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ + - ]
[ - + ][ + - ]
[ # # ]
267 : :
268 : : // TODO: we could first create the formatter, then the handler. This would allow
269 : : // passing the formatter as value in the component context, so the handler would
270 : : // not create an own default formatter
271 : : }
272 : 0 : catch( const Exception& )
273 : : {
274 : : DBG_UNHANDLED_EXCEPTION();
275 : : }
276 : : }
277 : :
278 : : //........................................................................
279 : : } // namespace logging
280 : : //........................................................................
281 : :
282 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|