1 /*************************************************************************
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * Copyright 2000, 2010 Oracle and/or its affiliates.
6 * OpenOffice.org - a multi-platform office productivity suite
8 * This file is part of OpenOffice.org.
10 * OpenOffice.org is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License version 3
12 * only, as published by the Free Software Foundation.
14 * OpenOffice.org is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License version 3 for more details
18 * (a copy is included in the LICENSE file that accompanied this code).
20 * You should have received a copy of the GNU Lesser General Public License
21 * version 3 along with OpenOffice.org. If not, see
22 * <http://www.openoffice.org/license.html>
23 * for a copy of the LGPLv3 License.
25 ************************************************************************/
27 // MARKER(update_precomp.py): autogen include statement, do not remove
28 #include "precompiled_extensions.hxx"
30 #include "log_module.hxx"
35 /** === begin UNO includes === **/
36 #ifndef _COM_SUN_STAR_LOGGING_XLOGFORMATTER_HPP_
37 #include <com/sun/star/logging/XCsvLogFormatter.hpp>
39 #ifndef _COM_SUN_STAR_LOGGING_XLOGFORMATTER_HPP_
40 #include <com/sun/star/logging/XLogFormatter.hpp>
42 #ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
43 #include <com/sun/star/uno/XComponentContext.hpp>
45 #ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
46 #include <com/sun/star/lang/XServiceInfo.hpp>
48 /** === end UNO includes === **/
50 #include <comphelper/componentcontext.hxx>
52 #include <cppuhelper/implbase2.hxx>
54 #include <rtl/ustrbuf.hxx>
56 #include <osl/thread.h>
61 /** === begin UNO using === **/
62 using ::com::sun::star::logging::XCsvLogFormatter
;
63 using ::com::sun::star::logging::XLogFormatter
;
64 using ::com::sun::star::uno::XComponentContext
;
65 using ::com::sun::star::uno::Reference
;
66 using ::com::sun::star::uno::Sequence
;
67 using ::com::sun::star::lang::XServiceInfo
;
68 using ::com::sun::star::uno::RuntimeException
;
69 using ::com::sun::star::logging::LogRecord
;
70 using ::com::sun::star::uno::XInterface
;
71 /** === end UNO using === **/
73 //= CsvFormatter - declaration
74 //= formats for csv files as defined by RFC4180
75 typedef ::cppu::WeakImplHelper2
< XCsvLogFormatter
78 class CsvFormatter
: public CsvFormatter_Base
81 virtual ::rtl::OUString SAL_CALL
formatMultiColumn(const Sequence
< ::rtl::OUString
>& column_data
) throw (RuntimeException
);
83 // XServiceInfo - static version
84 static ::rtl::OUString SAL_CALL
getImplementationName_static();
85 static Sequence
< ::rtl::OUString
> SAL_CALL
getSupportedServiceNames_static();
86 static Reference
< XInterface
> Create( const Reference
< XComponentContext
>& context
);
89 CsvFormatter( const Reference
< XComponentContext
>& context
);
90 virtual ~CsvFormatter();
93 virtual ::sal_Bool SAL_CALL
getLogEventNo() throw (RuntimeException
);
94 virtual ::sal_Bool SAL_CALL
getLogThread() throw (RuntimeException
);
95 virtual ::sal_Bool SAL_CALL
getLogTimestamp() throw (RuntimeException
);
96 virtual ::sal_Bool SAL_CALL
getLogSource() throw (RuntimeException
);
97 virtual Sequence
< ::rtl::OUString
> SAL_CALL
getColumnnames() throw (RuntimeException
);
99 virtual void SAL_CALL
setLogEventNo( ::sal_Bool log_event_no
) throw (RuntimeException
);
100 virtual void SAL_CALL
setLogThread( ::sal_Bool log_thread
) throw (RuntimeException
);
101 virtual void SAL_CALL
setLogTimestamp( ::sal_Bool log_timestamp
) throw (RuntimeException
);
102 virtual void SAL_CALL
setLogSource( ::sal_Bool log_source
) throw (RuntimeException
);
103 virtual void SAL_CALL
setColumnnames( const Sequence
< ::rtl::OUString
>& column_names
) throw (RuntimeException
);
106 virtual ::rtl::OUString SAL_CALL
getHead( ) throw (RuntimeException
);
107 virtual ::rtl::OUString SAL_CALL
format( const LogRecord
& Record
) throw (RuntimeException
);
108 virtual ::rtl::OUString SAL_CALL
getTail( ) throw (RuntimeException
);
111 virtual ::rtl::OUString SAL_CALL
getImplementationName() throw(RuntimeException
);
112 virtual ::sal_Bool SAL_CALL
supportsService( const ::rtl::OUString
& service_name
) throw(RuntimeException
);
113 virtual Sequence
< ::rtl::OUString
> SAL_CALL
getSupportedServiceNames() throw(RuntimeException
);
116 ::comphelper::ComponentContext m_aContext
;
117 ::sal_Bool m_LogEventNo
;
118 ::sal_Bool m_LogThread
;
119 ::sal_Bool m_LogTimestamp
;
120 ::sal_Bool m_LogSource
;
121 ::sal_Bool m_MultiColumn
;
122 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> m_Columnnames
;
124 } // namespace logging
129 const sal_Unicode quote_char
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"")).toChar();
130 const sal_Unicode comma_char
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(",")).toChar();
131 const ::rtl::OUString dos_newline
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\r\n"));
133 inline bool needsQuoting(const ::rtl::OUString
& str
)
135 static const ::rtl::OUString quote_trigger_chars
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("\",\n\r"));
136 sal_Int32 len
= str
.getLength();
137 for(sal_Int32 i
=0; i
<len
; i
++)
138 if(quote_trigger_chars
.indexOf(str
[i
])!=-1)
143 inline void appendEncodedString(::rtl::OUStringBuffer
& buf
, const ::rtl::OUString
& str
)
145 if(needsQuoting(str
))
147 // each double-quote will get replaced by two double-quotes
148 buf
.append(quote_char
);
149 const sal_Int32 buf_offset
= buf
.getLength();
150 const sal_Int32 str_length
= str
.getLength();
152 // special treatment for the last character
153 if(quote_char
==str
[str_length
-1])
154 buf
.append(quote_char
);
155 // iterating backwards because the index at which we insert wont be shifted
156 // when moving that way.
157 for(sal_Int32 i
= str_length
; i
>=0; )
159 i
=str
.lastIndexOf(quote_char
, --i
);
161 buf
.insert(buf_offset
+ i
, quote_char
);
163 buf
.append(quote_char
);
169 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> initialColumns()
171 com::sun::star::uno::Sequence
< ::rtl::OUString
> result
= ::com::sun::star::uno::Sequence
< ::rtl::OUString
>(1);
172 result
[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("message"));
177 //= CsvFormatter - implementation
180 CsvFormatter::CsvFormatter( const Reference
< XComponentContext
>& context
)
181 :m_aContext( context
),
184 m_LogTimestamp(true),
186 m_MultiColumn(false),
187 m_Columnnames(initialColumns())
190 CsvFormatter::~CsvFormatter()
193 ::sal_Bool
CsvFormatter::getLogEventNo() throw (RuntimeException
)
198 ::sal_Bool
CsvFormatter::getLogThread() throw (RuntimeException
)
203 ::sal_Bool
CsvFormatter::getLogTimestamp() throw (RuntimeException
)
205 return m_LogTimestamp
;
208 ::sal_Bool
CsvFormatter::getLogSource() throw (RuntimeException
)
213 Sequence
< ::rtl::OUString
> CsvFormatter::getColumnnames() throw (RuntimeException
)
215 return m_Columnnames
;
218 void CsvFormatter::setLogEventNo(::sal_Bool log_event_no
) throw (RuntimeException
)
220 m_LogEventNo
= log_event_no
;
223 void CsvFormatter::setLogThread(::sal_Bool log_thread
) throw (RuntimeException
)
225 m_LogThread
= log_thread
;
228 void CsvFormatter::setLogTimestamp(::sal_Bool log_timestamp
) throw (RuntimeException
)
230 m_LogTimestamp
= log_timestamp
;
233 void CsvFormatter::setLogSource(::sal_Bool log_source
) throw (RuntimeException
)
235 m_LogSource
= log_source
;
238 void CsvFormatter::setColumnnames(const Sequence
< ::rtl::OUString
>& columnnames
) throw (RuntimeException
)
240 m_Columnnames
= Sequence
< ::rtl::OUString
>(columnnames
);
241 m_MultiColumn
= (m_Columnnames
.getLength()>1);
244 ::rtl::OUString SAL_CALL
CsvFormatter::getHead( ) throw (RuntimeException
)
246 ::rtl::OUStringBuffer buf
;
248 buf
.appendAscii("event no,");
250 buf
.appendAscii("thread,");
252 buf
.appendAscii("timestamp,");
254 buf
.appendAscii("class,method,");
255 sal_Int32 columns
= m_Columnnames
.getLength();
256 for(sal_Int32 i
=0; i
<columns
; i
++)
258 buf
.append(m_Columnnames
[i
]);
259 buf
.append(comma_char
);
261 buf
.setLength(buf
.getLength()-1);
262 buf
.append(dos_newline
);
263 return buf
.makeStringAndClear();
266 ::rtl::OUString SAL_CALL
CsvFormatter::format( const LogRecord
& record
) throw (RuntimeException
)
268 ::rtl::OUStringBuffer aLogEntry
;
272 aLogEntry
.append( record
.SequenceNumber
);
273 aLogEntry
.append(comma_char
);
278 aLogEntry
.append( record
.ThreadID
);
279 aLogEntry
.append(comma_char
);
286 const size_t buffer_size
= sizeof( buffer
);
287 snprintf( buffer
, buffer_size
, "%04i-%02i-%02iT%02i:%02i:%02i.%02i",
288 (int)record
.LogTime
.Year
,
289 (int)record
.LogTime
.Month
,
290 (int)record
.LogTime
.Day
,
291 (int)record
.LogTime
.Hours
,
292 (int)record
.LogTime
.Minutes
,
293 (int)record
.LogTime
.Seconds
,
294 (int)record
.LogTime
.HundredthSeconds
);
295 aLogEntry
.appendAscii( buffer
);
296 aLogEntry
.append(comma_char
);
301 appendEncodedString(aLogEntry
, record
.SourceClassName
);
302 aLogEntry
.append(comma_char
);
304 appendEncodedString(aLogEntry
, record
.SourceMethodName
);
305 aLogEntry
.append(comma_char
);
308 // if the CsvFormatter has multiple columns set via setColumnnames(), the
309 // message of the record is expected to be encoded with formatMultiColumn
310 // if the CsvFormatter has only one column set, the message is expected not
313 aLogEntry
.append(record
.Message
);
315 appendEncodedString(aLogEntry
, record
.Message
);
317 aLogEntry
.append( dos_newline
);
318 return aLogEntry
.makeStringAndClear();
321 ::rtl::OUString SAL_CALL
CsvFormatter::getTail( ) throw (RuntimeException
)
323 return ::rtl::OUString();
326 ::rtl::OUString SAL_CALL
CsvFormatter::formatMultiColumn(const Sequence
< ::rtl::OUString
>& column_data
) throw (RuntimeException
)
328 sal_Int32 columns
= column_data
.getLength();
329 ::rtl::OUStringBuffer buf
;
330 for(int i
=0; i
<columns
; i
++)
332 appendEncodedString(buf
, column_data
[i
]);
333 buf
.append(comma_char
);
335 buf
.setLength(buf
.getLength()-1);
336 return buf
.makeStringAndClear();
339 ::sal_Bool SAL_CALL
CsvFormatter::supportsService( const ::rtl::OUString
& service_name
) throw(RuntimeException
)
341 const Sequence
< ::rtl::OUString
> aServiceNames( getSupportedServiceNames() );
342 for ( const ::rtl::OUString
* pServiceNames
= aServiceNames
.getConstArray();
343 pServiceNames
!= aServiceNames
.getConstArray() + aServiceNames
.getLength();
346 if ( service_name
== *pServiceNames
)
351 ::rtl::OUString SAL_CALL
CsvFormatter::getImplementationName() throw(RuntimeException
)
353 return getImplementationName_static();
356 Sequence
< ::rtl::OUString
> SAL_CALL
CsvFormatter::getSupportedServiceNames() throw(RuntimeException
)
358 return getSupportedServiceNames_static();
361 ::rtl::OUString SAL_CALL
CsvFormatter::getImplementationName_static()
363 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.CsvFormatter" ) );
366 Sequence
< ::rtl::OUString
> SAL_CALL
CsvFormatter::getSupportedServiceNames_static()
368 Sequence
< ::rtl::OUString
> aServiceNames(1);
369 aServiceNames
[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.logging.CsvFormatter" ) );
370 return aServiceNames
;
373 Reference
< XInterface
> CsvFormatter::Create( const Reference
< XComponentContext
>& context
)
375 return *( new CsvFormatter( context
) );
378 void createRegistryInfo_CsvFormatter()
380 static OAutoRegistration
< CsvFormatter
> aAutoRegistration
;
382 } // namespace logging