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