1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_extensions.hxx"
26 
27 #include "log_module.hxx"
28 #include "logrecord.hxx"
29 #include "loggerconfig.hxx"
30 
31 /** === begin UNO includes === **/
32 #include <com/sun/star/logging/XLogger.hpp>
33 #include <com/sun/star/logging/LogLevel.hpp>
34 #include <com/sun/star/uno/XComponentContext.hpp>
35 #include <com/sun/star/lang/XServiceInfo.hpp>
36 #include <com/sun/star/logging/XLoggerPool.hpp>
37 /** === end UNO includes === **/
38 
39 #include <tools/diagnose_ex.h>
40 
41 #include <comphelper/componentcontext.hxx>
42 
43 #include <cppuhelper/basemutex.hxx>
44 #include <cppuhelper/interfacecontainer.hxx>
45 #include <cppuhelper/implbase2.hxx>
46 #include <cppuhelper/weakref.hxx>
47 
48 #include <boost/bind.hpp>
49 
50 #include <map>
51 
52 //........................................................................
53 namespace logging
54 {
55 //........................................................................
56 
57 	/** === begin UNO using === **/
58     using ::com::sun::star::logging::XLogger;
59     using ::com::sun::star::uno::Reference;
60     using ::com::sun::star::uno::XComponentContext;
61     using ::com::sun::star::lang::XServiceInfo;
62     using ::com::sun::star::uno::RuntimeException;
63     using ::com::sun::star::uno::Sequence;
64     using ::com::sun::star::uno::XInterface;
65     using ::com::sun::star::uno::UNO_QUERY_THROW;
66     using ::com::sun::star::uno::Any;
67     using ::com::sun::star::uno::Exception;
68     using ::com::sun::star::uno::WeakReference;
69     using ::com::sun::star::logging::XLogHandler;
70     using ::com::sun::star::logging::XLoggerPool;
71     using ::com::sun::star::logging::LogRecord;
72 	/** === end UNO using === **/
73     namespace LogLevel = ::com::sun::star::logging::LogLevel;
74 
75 	//====================================================================
76 	//= helper
77 	//====================================================================
78     namespace
79     {
lcl_supportsService_nothrow(XServiceInfo & _rSI,const::rtl::OUString & _rServiceName)80         sal_Bool lcl_supportsService_nothrow( XServiceInfo& _rSI, const ::rtl::OUString& _rServiceName )
81         {
82             const Sequence< ::rtl::OUString > aServiceNames( _rSI.getSupportedServiceNames() );
83             for (   const ::rtl::OUString* pServiceNames = aServiceNames.getConstArray();
84                     pServiceNames != aServiceNames.getConstArray() + aServiceNames.getLength();
85                     ++pServiceNames
86                 )
87                 if ( _rServiceName == *pServiceNames )
88                     return sal_True;
89             return sal_False;
90         }
91     }
92 
93 	//====================================================================
94 	//= EventLogger - declaration
95 	//====================================================================
96     typedef ::cppu::WeakImplHelper2 <   XLogger
97                                     ,   XServiceInfo
98                                     >   EventLogger_Base;
99     class EventLogger   :public ::cppu::BaseMutex
100                         ,public EventLogger_Base
101     {
102     private:
103         ::comphelper::ComponentContext      m_aContext;
104         ::cppu::OInterfaceContainerHelper   m_aHandlers;
105         oslInterlockedCount                 m_nEventNumber;
106 
107         // <attributes>
108         sal_Int32       m_nLogLevel;
109         ::rtl::OUString m_sName;
110         // </attributes>
111 
112     public:
113         EventLogger( const Reference< XComponentContext >& _rxContext, const ::rtl::OUString& _rName );
114 
115         // XServiceInfo
116 		virtual ::rtl::OUString SAL_CALL getImplementationName() throw(RuntimeException);
117         virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException);
118         virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(RuntimeException);
119 
120         // XLogger
121         virtual ::rtl::OUString SAL_CALL getName() throw (RuntimeException);
122         virtual ::sal_Int32 SAL_CALL getLevel() throw (RuntimeException);
123         virtual void SAL_CALL setLevel( ::sal_Int32 _level ) throw (RuntimeException);
124         virtual void SAL_CALL addLogHandler( const Reference< XLogHandler >& LogHandler ) throw (RuntimeException);
125         virtual void SAL_CALL removeLogHandler( const Reference< XLogHandler >& LogHandler ) throw (RuntimeException);
126         virtual ::sal_Bool SAL_CALL isLoggable( ::sal_Int32 _nLevel ) throw (RuntimeException);
127         virtual void SAL_CALL log( ::sal_Int32 Level, const ::rtl::OUString& Message ) throw (RuntimeException);
128         virtual void SAL_CALL logp( ::sal_Int32 Level, const ::rtl::OUString& SourceClass, const ::rtl::OUString& SourceMethod, const ::rtl::OUString& Message ) throw (RuntimeException);
129 
130     protected:
131         ~EventLogger();
132 
133     private:
134         /** logs the given log record
135         */
136         void    impl_ts_logEvent_nothrow( const LogRecord& _rRecord );
137 
138         /** non-threadsafe impl-version of isLoggable
139         */
140         bool    impl_nts_isLoggable_nothrow( ::sal_Int32 _nLevel );
141     };
142 
143 	//====================================================================
144 	//= LoggerPool - declaration
145 	//====================================================================
146     typedef ::cppu::WeakImplHelper2 <   XLoggerPool
147                                     ,   XServiceInfo
148                                     >   LoggerPool_Base;
149     /** administrates a pool of XLogger instances, where a logger is keyed by its name,
150         and subsequent requests for a logger with the same name return the same instance.
151     */
152     class LoggerPool : public LoggerPool_Base
153     {
154     private:
155         typedef ::std::map< ::rtl::OUString, WeakReference< XLogger > > ImplPool;
156 
157     private:
158         ::osl::Mutex                    m_aMutex;
159         ::comphelper::ComponentContext  m_aContext;
160         ImplPool                        m_aImpl;
161 
162     public:
163         LoggerPool( const Reference< XComponentContext >& _rxContext );
164 
165         // XServiceInfo
166 		virtual ::rtl::OUString SAL_CALL getImplementationName() throw(RuntimeException);
167         virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException);
168         virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(RuntimeException);
169 
170         // helper for factories
171         static Sequence< ::rtl::OUString > getSupportedServiceNames_static();
172         static ::rtl::OUString  getImplementationName_static();
173         static ::rtl::OUString  getSingletonName_static();
174         static Reference< XInterface > Create( const Reference< XComponentContext >& _rxContext );
175 
176         // XLoggerPool
177         virtual Reference< XLogger > SAL_CALL getNamedLogger( const ::rtl::OUString& Name ) throw (RuntimeException);
178         virtual Reference< XLogger > SAL_CALL getDefaultLogger(  ) throw (RuntimeException);
179     };
180 
181 	//====================================================================
182 	//= EventLogger - implementation
183 	//====================================================================
184 	//--------------------------------------------------------------------
EventLogger(const Reference<XComponentContext> & _rxContext,const::rtl::OUString & _rName)185     EventLogger::EventLogger( const Reference< XComponentContext >& _rxContext, const ::rtl::OUString& _rName )
186         :m_aContext( _rxContext )
187         ,m_aHandlers( m_aMutex )
188         ,m_nEventNumber( 0 )
189         ,m_nLogLevel( LogLevel::OFF )
190         ,m_sName( _rName )
191     {
192         osl_incrementInterlockedCount( &m_refCount );
193         {
194             initializeLoggerFromConfiguration( m_aContext, this );
195         }
196         osl_decrementInterlockedCount( &m_refCount );
197     }
198 
199 	//--------------------------------------------------------------------
~EventLogger()200     EventLogger::~EventLogger()
201     {
202     }
203 
204     //--------------------------------------------------------------------
impl_nts_isLoggable_nothrow(::sal_Int32 _nLevel)205     bool EventLogger::impl_nts_isLoggable_nothrow( ::sal_Int32 _nLevel )
206     {
207         if ( _nLevel < m_nLogLevel )
208             return false;
209 
210         if ( !m_aHandlers.getLength() )
211             return false;
212 
213         return true;
214     }
215 
216     //--------------------------------------------------------------------
impl_ts_logEvent_nothrow(const LogRecord & _rRecord)217     void EventLogger::impl_ts_logEvent_nothrow( const LogRecord& _rRecord )
218     {
219         ::osl::MutexGuard aGuard( m_aMutex );
220 
221         if ( !impl_nts_isLoggable_nothrow( _rRecord.Level ) )
222             return;
223 
224         m_aHandlers.forEach< XLogHandler >(
225             ::boost::bind( &XLogHandler::publish, _1, ::boost::cref( _rRecord ) ) );
226         m_aHandlers.forEach< XLogHandler >(
227             ::boost::bind( &XLogHandler::flush, _1 ) );
228     }
229 
230     //--------------------------------------------------------------------
getName()231     ::rtl::OUString SAL_CALL EventLogger::getName() throw (RuntimeException)
232     {
233         return m_sName;
234     }
235 
236     //--------------------------------------------------------------------
getLevel()237     ::sal_Int32 SAL_CALL EventLogger::getLevel() throw (RuntimeException)
238     {
239         ::osl::MutexGuard aGuard( m_aMutex );
240         return m_nLogLevel;
241     }
242 
243     //--------------------------------------------------------------------
setLevel(::sal_Int32 _level)244     void SAL_CALL EventLogger::setLevel( ::sal_Int32 _level ) throw (RuntimeException)
245     {
246         ::osl::MutexGuard aGuard( m_aMutex );
247         m_nLogLevel = _level;
248     }
249 
250     //--------------------------------------------------------------------
addLogHandler(const Reference<XLogHandler> & _rxLogHandler)251     void SAL_CALL EventLogger::addLogHandler( const Reference< XLogHandler >& _rxLogHandler ) throw (RuntimeException)
252     {
253         if ( _rxLogHandler.is() )
254             m_aHandlers.addInterface( _rxLogHandler );
255     }
256 
257     //--------------------------------------------------------------------
removeLogHandler(const Reference<XLogHandler> & _rxLogHandler)258     void SAL_CALL EventLogger::removeLogHandler( const Reference< XLogHandler >& _rxLogHandler ) throw (RuntimeException)
259     {
260         if ( _rxLogHandler.is() )
261             m_aHandlers.removeInterface( _rxLogHandler );
262     }
263 
264     //--------------------------------------------------------------------
isLoggable(::sal_Int32 _nLevel)265     ::sal_Bool SAL_CALL EventLogger::isLoggable( ::sal_Int32 _nLevel ) throw (RuntimeException)
266     {
267         ::osl::MutexGuard aGuard( m_aMutex );
268         return impl_nts_isLoggable_nothrow( _nLevel );
269     }
270 
271     //--------------------------------------------------------------------
log(::sal_Int32 _nLevel,const::rtl::OUString & _rMessage)272     void SAL_CALL EventLogger::log( ::sal_Int32 _nLevel, const ::rtl::OUString& _rMessage ) throw (RuntimeException)
273     {
274         impl_ts_logEvent_nothrow( createLogRecord(
275             m_sName,
276             _rMessage,
277             _nLevel,
278             osl_incrementInterlockedCount( &m_nEventNumber )
279         ) );
280     }
281 
282     //--------------------------------------------------------------------
logp(::sal_Int32 _nLevel,const::rtl::OUString & _rSourceClass,const::rtl::OUString & _rSourceMethod,const::rtl::OUString & _rMessage)283     void SAL_CALL EventLogger::logp( ::sal_Int32 _nLevel, const ::rtl::OUString& _rSourceClass, const ::rtl::OUString& _rSourceMethod, const ::rtl::OUString& _rMessage ) throw (RuntimeException)
284     {
285         impl_ts_logEvent_nothrow( createLogRecord(
286             m_sName,
287             _rSourceClass,
288             _rSourceMethod,
289             _rMessage,
290             _nLevel,
291             osl_incrementInterlockedCount( &m_nEventNumber )
292         ) );
293     }
294 
295     //--------------------------------------------------------------------
getImplementationName()296     ::rtl::OUString SAL_CALL EventLogger::getImplementationName() throw(RuntimeException)
297     {
298         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.EventLogger" ) );
299     }
300 
301     //--------------------------------------------------------------------
supportsService(const::rtl::OUString & _rServiceName)302     ::sal_Bool EventLogger::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException)
303     {
304         return lcl_supportsService_nothrow( *this, _rServiceName );
305     }
306 
307     //--------------------------------------------------------------------
getSupportedServiceNames()308     Sequence< ::rtl::OUString > SAL_CALL EventLogger::getSupportedServiceNames() throw(RuntimeException)
309     {
310         Sequence< ::rtl::OUString > aServiceNames(1);
311         aServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.logging.Logger" ) );
312         return aServiceNames;
313     }
314 
315 	//====================================================================
316 	//= LoggerPool - implementation
317 	//====================================================================
318     //--------------------------------------------------------------------
LoggerPool(const Reference<XComponentContext> & _rxContext)319     LoggerPool::LoggerPool( const Reference< XComponentContext >& _rxContext )
320         :m_aContext( _rxContext )
321     {
322     }
323 
324     //--------------------------------------------------------------------
getImplementationName()325     ::rtl::OUString SAL_CALL LoggerPool::getImplementationName() throw(RuntimeException)
326     {
327         return getImplementationName_static();
328     }
329 
330     //--------------------------------------------------------------------
supportsService(const::rtl::OUString & _rServiceName)331     ::sal_Bool SAL_CALL LoggerPool::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException)
332     {
333         return lcl_supportsService_nothrow( *this, _rServiceName );
334     }
335 
336     //--------------------------------------------------------------------
getSupportedServiceNames()337     Sequence< ::rtl::OUString > SAL_CALL LoggerPool::getSupportedServiceNames() throw(RuntimeException)
338     {
339         return getSupportedServiceNames_static();
340     }
341 
342     //--------------------------------------------------------------------
getImplementationName_static()343     ::rtl::OUString SAL_CALL LoggerPool::getImplementationName_static()
344     {
345         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.LoggerPool" ) );
346     }
347 
348     //--------------------------------------------------------------------
getSupportedServiceNames_static()349     Sequence< ::rtl::OUString > SAL_CALL LoggerPool::getSupportedServiceNames_static()
350     {
351         Sequence< ::rtl::OUString > aServiceNames(1);
352         aServiceNames[0] = getSingletonName_static();
353         return aServiceNames;
354     }
355 
356     //--------------------------------------------------------------------
getSingletonName_static()357     ::rtl::OUString LoggerPool::getSingletonName_static()
358     {
359         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.logging.LoggerPool" ) );
360     }
361 
362     //--------------------------------------------------------------------
Create(const Reference<XComponentContext> & _rxContext)363     Reference< XInterface > SAL_CALL LoggerPool::Create( const Reference< XComponentContext >& _rxContext )
364     {
365         return *( new LoggerPool( _rxContext ) );
366     }
367 
368     //--------------------------------------------------------------------
getNamedLogger(const::rtl::OUString & _rName)369     Reference< XLogger > SAL_CALL LoggerPool::getNamedLogger( const ::rtl::OUString& _rName ) throw (RuntimeException)
370     {
371         ::osl::MutexGuard aGuard( m_aMutex );
372 
373         WeakReference< XLogger >& rLogger( m_aImpl[ _rName ] );
374         Reference< XLogger > xLogger( (Reference< XLogger >)rLogger );
375         if ( !xLogger.is() )
376         {
377             // never requested before, or already dead
378             xLogger = new EventLogger( m_aContext.getUNOContext(), _rName );
379             rLogger = xLogger;
380         }
381 
382         return xLogger;
383     }
384 
385     //--------------------------------------------------------------------
getDefaultLogger()386     Reference< XLogger > SAL_CALL LoggerPool::getDefaultLogger(  ) throw (RuntimeException)
387     {
388         return getNamedLogger( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.logging.DefaultLogger" ) ) );
389     }
390 
391     //--------------------------------------------------------------------
createRegistryInfo_LoggerPool()392     void createRegistryInfo_LoggerPool()
393     {
394         static OSingletonRegistration< LoggerPool > aAutoRegistration;
395     }
396 
397 //........................................................................
398 } // namespace logging
399 //........................................................................
400 
401