xref: /AOO41X/main/extensions/source/logging/loggerconfig.cxx (revision 2a97ec55f1442d65917e8c8b82a55ab76c9ff676)
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