1 /*************************************************************************
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * Copyright 2008 by Sun Microsystems, Inc.
6 * OpenOffice.org - a multi-platform office productivity suite
8 * $RCSfile: csvformatter.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
28 ************************************************************************/
30 // MARKER(update_precomp.py): autogen include statement, do not remove
31 #include "precompiled_extensions.hxx"
33 #include "log_module.hxx"
38 /** === begin UNO includes === **/
39 #ifndef _COM_SUN_STAR_LOGGING_XLOGFORMATTER_HPP_
40 #include <com/sun/star/logging/XCsvLogFormatter.hpp>
42 #ifndef _COM_SUN_STAR_LOGGING_XLOGFORMATTER_HPP_
43 #include <com/sun/star/logging/XLogFormatter.hpp>
45 #ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
46 #include <com/sun/star/uno/XComponentContext.hpp>
48 #ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
49 #include <com/sun/star/lang/XServiceInfo.hpp>
51 /** === end UNO includes === **/
53 #include <comphelper/componentcontext.hxx>
55 #include <cppuhelper/implbase2.hxx>
57 #include <rtl/ustrbuf.hxx>
59 #include <osl/thread.h>
64 /** === begin UNO using === **/
65 using ::com::sun::star::logging::XCsvLogFormatter
;
66 using ::com::sun::star::logging::XLogFormatter
;
67 using ::com::sun::star::uno::XComponentContext
;
68 using ::com::sun::star::uno::Reference
;
69 using ::com::sun::star::uno::Sequence
;
70 using ::com::sun::star::lang::XServiceInfo
;
71 using ::com::sun::star::uno::RuntimeException
;
72 using ::com::sun::star::logging::LogRecord
;
73 using ::com::sun::star::uno::XInterface
;
74 /** === end UNO using === **/
76 //= CsvFormatter - declaration
77 //= formats for csv files as defined by RFC4180
78 typedef ::cppu::WeakImplHelper2
< XCsvLogFormatter
81 class CsvFormatter
: public CsvFormatter_Base
84 virtual ::rtl::OUString SAL_CALL
formatMultiColumn(const Sequence
< ::rtl::OUString
>& column_data
) throw (RuntimeException
);
86 // XServiceInfo - static version
87 static ::rtl::OUString SAL_CALL
getImplementationName_static();
88 static Sequence
< ::rtl::OUString
> SAL_CALL
getSupportedServiceNames_static();
89 static Reference
< XInterface
> Create( const Reference
< XComponentContext
>& context
);
92 CsvFormatter( const Reference
< XComponentContext
>& context
);
93 virtual ~CsvFormatter();
96 virtual ::sal_Bool SAL_CALL
getLogEventNo() throw (RuntimeException
);
97 virtual ::sal_Bool SAL_CALL
getLogThread() throw (RuntimeException
);
98 virtual ::sal_Bool SAL_CALL
getLogTimestamp() throw (RuntimeException
);
99 virtual ::sal_Bool SAL_CALL
getLogSource() throw (RuntimeException
);
100 virtual Sequence
< ::rtl::OUString
> SAL_CALL
getColumnnames() throw (RuntimeException
);
102 virtual void SAL_CALL
setLogEventNo( ::sal_Bool log_event_no
) throw (RuntimeException
);
103 virtual void SAL_CALL
setLogThread( ::sal_Bool log_thread
) throw (RuntimeException
);
104 virtual void SAL_CALL
setLogTimestamp( ::sal_Bool log_timestamp
) throw (RuntimeException
);
105 virtual void SAL_CALL
setLogSource( ::sal_Bool log_source
) throw (RuntimeException
);
106 virtual void SAL_CALL
setColumnnames( const Sequence
< ::rtl::OUString
>& column_names
) throw (RuntimeException
);
109 virtual ::rtl::OUString SAL_CALL
getHead( ) throw (RuntimeException
);
110 virtual ::rtl::OUString SAL_CALL
format( const LogRecord
& Record
) throw (RuntimeException
);
111 virtual ::rtl::OUString SAL_CALL
getTail( ) throw (RuntimeException
);
114 virtual ::rtl::OUString SAL_CALL
getImplementationName() throw(RuntimeException
);
115 virtual ::sal_Bool SAL_CALL
supportsService( const ::rtl::OUString
& service_name
) throw(RuntimeException
);
116 virtual Sequence
< ::rtl::OUString
> SAL_CALL
getSupportedServiceNames() throw(RuntimeException
);
119 ::comphelper::ComponentContext m_aContext
;
120 ::sal_Bool m_LogEventNo
;
121 ::sal_Bool m_LogThread
;
122 ::sal_Bool m_LogTimestamp
;
123 ::sal_Bool m_LogSource
;
124 ::sal_Bool m_MultiColumn
;
125 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> m_Columnnames
;
127 } // namespace logging
132 const sal_Unicode quote_char
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"")).toChar();
133 const sal_Unicode comma_char
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(",")).toChar();
134 const ::rtl::OUString dos_newline
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\r\n"));
136 inline bool needsQuoting(const ::rtl::OUString
& str
)
138 static const ::rtl::OUString quote_trigger_chars
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("\",\n\r"));
139 sal_Int32 len
= str
.getLength();
140 for(sal_Int32 i
=0; i
<len
; i
++)
141 if(quote_trigger_chars
.indexOf(str
[i
])!=-1)
146 inline void appendEncodedString(::rtl::OUStringBuffer
& buf
, const ::rtl::OUString
& str
)
148 if(needsQuoting(str
))
150 // each double-quote will get replaced by two double-quotes
151 buf
.append(quote_char
);
152 const sal_Int32 buf_offset
= buf
.getLength();
153 const sal_Int32 str_length
= str
.getLength();
155 // special treatment for the last character
156 if(quote_char
==str
[str_length
-1])
157 buf
.append(quote_char
);
158 // iterating backwards because the index at which we insert wont be shifted
159 // when moving that way.
160 for(sal_Int32 i
= str_length
; i
>=0; )
162 i
=str
.lastIndexOf(quote_char
, --i
);
164 buf
.insert(buf_offset
+ i
, quote_char
);
166 buf
.append(quote_char
);
172 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> initialColumns()
174 com::sun::star::uno::Sequence
< ::rtl::OUString
> result
= ::com::sun::star::uno::Sequence
< ::rtl::OUString
>(1);
175 result
[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("message"));
180 //= CsvFormatter - implementation
183 CsvFormatter::CsvFormatter( const Reference
< XComponentContext
>& context
)
184 :m_aContext( context
),
187 m_LogTimestamp(true),
189 m_MultiColumn(false),
190 m_Columnnames(initialColumns())
193 CsvFormatter::~CsvFormatter()
196 ::sal_Bool
CsvFormatter::getLogEventNo() throw (RuntimeException
)
201 ::sal_Bool
CsvFormatter::getLogThread() throw (RuntimeException
)
206 ::sal_Bool
CsvFormatter::getLogTimestamp() throw (RuntimeException
)
208 return m_LogTimestamp
;
211 ::sal_Bool
CsvFormatter::getLogSource() throw (RuntimeException
)
216 Sequence
< ::rtl::OUString
> CsvFormatter::getColumnnames() throw (RuntimeException
)
218 return m_Columnnames
;
221 void CsvFormatter::setLogEventNo(::sal_Bool log_event_no
) throw (RuntimeException
)
223 m_LogEventNo
= log_event_no
;
226 void CsvFormatter::setLogThread(::sal_Bool log_thread
) throw (RuntimeException
)
228 m_LogThread
= log_thread
;
231 void CsvFormatter::setLogTimestamp(::sal_Bool log_timestamp
) throw (RuntimeException
)
233 m_LogTimestamp
= log_timestamp
;
236 void CsvFormatter::setLogSource(::sal_Bool log_source
) throw (RuntimeException
)
238 m_LogSource
= log_source
;
241 void CsvFormatter::setColumnnames(const Sequence
< ::rtl::OUString
>& columnnames
) throw (RuntimeException
)
243 m_Columnnames
= Sequence
< ::rtl::OUString
>(columnnames
);
244 m_MultiColumn
= (m_Columnnames
.getLength()>1);
247 ::rtl::OUString SAL_CALL
CsvFormatter::getHead( ) throw (RuntimeException
)
249 ::rtl::OUStringBuffer buf
;
251 buf
.appendAscii("event no,");
253 buf
.appendAscii("thread,");
255 buf
.appendAscii("timestamp,");
257 buf
.appendAscii("class,method,");
258 sal_Int32 columns
= m_Columnnames
.getLength();
259 for(sal_Int32 i
=0; i
<columns
; i
++)
261 buf
.append(m_Columnnames
[i
]);
262 buf
.append(comma_char
);
264 buf
.setLength(buf
.getLength()-1);
265 buf
.append(dos_newline
);
266 return buf
.makeStringAndClear();
269 ::rtl::OUString SAL_CALL
CsvFormatter::format( const LogRecord
& record
) throw (RuntimeException
)
271 ::rtl::OUStringBuffer aLogEntry
;
275 aLogEntry
.append( record
.SequenceNumber
);
276 aLogEntry
.append(comma_char
);
281 aLogEntry
.append( record
.ThreadID
);
282 aLogEntry
.append(comma_char
);
289 const size_t buffer_size
= sizeof( buffer
);
290 snprintf( buffer
, buffer_size
, "%04i-%02i-%02iT%02i:%02i:%02i.%02i",
291 (int)record
.LogTime
.Year
,
292 (int)record
.LogTime
.Month
,
293 (int)record
.LogTime
.Day
,
294 (int)record
.LogTime
.Hours
,
295 (int)record
.LogTime
.Minutes
,
296 (int)record
.LogTime
.Seconds
,
297 (int)record
.LogTime
.HundredthSeconds
);
298 aLogEntry
.appendAscii( buffer
);
299 aLogEntry
.append(comma_char
);
304 appendEncodedString(aLogEntry
, record
.SourceClassName
);
305 aLogEntry
.append(comma_char
);
307 appendEncodedString(aLogEntry
, record
.SourceMethodName
);
308 aLogEntry
.append(comma_char
);
311 // if the CsvFormatter has multiple columns set via setColumnnames(), the
312 // message of the record is expected to be encoded with formatMultiColumn
313 // if the CsvFormatter has only one column set, the message is expected not
316 aLogEntry
.append(record
.Message
);
318 appendEncodedString(aLogEntry
, record
.Message
);
320 aLogEntry
.append( dos_newline
);
321 return aLogEntry
.makeStringAndClear();
324 ::rtl::OUString SAL_CALL
CsvFormatter::getTail( ) throw (RuntimeException
)
326 return ::rtl::OUString();
329 ::rtl::OUString SAL_CALL
CsvFormatter::formatMultiColumn(const Sequence
< ::rtl::OUString
>& column_data
) throw (RuntimeException
)
331 sal_Int32 columns
= column_data
.getLength();
332 ::rtl::OUStringBuffer buf
;
333 for(int i
=0; i
<columns
; i
++)
335 appendEncodedString(buf
, column_data
[i
]);
336 buf
.append(comma_char
);
338 buf
.setLength(buf
.getLength()-1);
339 return buf
.makeStringAndClear();
342 ::sal_Bool SAL_CALL
CsvFormatter::supportsService( const ::rtl::OUString
& service_name
) throw(RuntimeException
)
344 const Sequence
< ::rtl::OUString
> aServiceNames( getSupportedServiceNames() );
345 for ( const ::rtl::OUString
* pServiceNames
= aServiceNames
.getConstArray();
346 pServiceNames
!= aServiceNames
.getConstArray() + aServiceNames
.getLength();
349 if ( service_name
== *pServiceNames
)
354 ::rtl::OUString SAL_CALL
CsvFormatter::getImplementationName() throw(RuntimeException
)
356 return getImplementationName_static();
359 Sequence
< ::rtl::OUString
> SAL_CALL
CsvFormatter::getSupportedServiceNames() throw(RuntimeException
)
361 return getSupportedServiceNames_static();
364 ::rtl::OUString SAL_CALL
CsvFormatter::getImplementationName_static()
366 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.CsvFormatter" ) );
369 Sequence
< ::rtl::OUString
> SAL_CALL
CsvFormatter::getSupportedServiceNames_static()
371 Sequence
< ::rtl::OUString
> aServiceNames(1);
372 aServiceNames
[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.logging.CsvFormatter" ) );
373 return aServiceNames
;
376 Reference
< XInterface
> CsvFormatter::Create( const Reference
< XComponentContext
>& context
)
378 return *( new CsvFormatter( context
) );
381 void createRegistryInfo_CsvFormatter()
383 static OAutoRegistration
< CsvFormatter
> aAutoRegistration
;
385 } // namespace logging