masterfix DEV300: #i10000# build fix
[LibreOffice.git] / extensions / source / logging / csvformatter.cxx
blob5e02e5f7cb697d7d4adff8d7fff6ae88ddab8334
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"
32 #include <stdio.h>
33 #include <string>
35 /** === begin UNO includes === **/
36 #ifndef _COM_SUN_STAR_LOGGING_XLOGFORMATTER_HPP_
37 #include <com/sun/star/logging/XCsvLogFormatter.hpp>
38 #endif
39 #ifndef _COM_SUN_STAR_LOGGING_XLOGFORMATTER_HPP_
40 #include <com/sun/star/logging/XLogFormatter.hpp>
41 #endif
42 #ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
43 #include <com/sun/star/uno/XComponentContext.hpp>
44 #endif
45 #ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
46 #include <com/sun/star/lang/XServiceInfo.hpp>
47 #endif
48 /** === end UNO includes === **/
50 #include <comphelper/componentcontext.hxx>
52 #include <cppuhelper/implbase2.hxx>
54 #include <rtl/ustrbuf.hxx>
56 #include <osl/thread.h>
58 namespace logging
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
76 , XServiceInfo
77 > CsvFormatter_Base;
78 class CsvFormatter : public CsvFormatter_Base
80 public:
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 );
88 protected:
89 CsvFormatter( const Reference< XComponentContext >& context );
90 virtual ~CsvFormatter();
92 // XCsvLogFormatter
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);
105 // XLogFormatter
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);
110 // XServiceInfo
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);
115 private:
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
126 //= private helpers
127 namespace
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)
139 return true;
140 return false;
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();
151 buf.append(str);
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);
160 if(i!=-1)
161 buf.insert(buf_offset + i, quote_char);
163 buf.append(quote_char);
165 else
166 buf.append(str);
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"));
173 return result;
177 //= CsvFormatter - implementation
178 namespace logging
180 CsvFormatter::CsvFormatter( const Reference< XComponentContext >& context )
181 :m_aContext( context ),
182 m_LogEventNo(true),
183 m_LogThread(true),
184 m_LogTimestamp(true),
185 m_LogSource(false),
186 m_MultiColumn(false),
187 m_Columnnames(initialColumns())
190 CsvFormatter::~CsvFormatter()
193 ::sal_Bool CsvFormatter::getLogEventNo() throw (RuntimeException)
195 return m_LogEventNo;
198 ::sal_Bool CsvFormatter::getLogThread() throw (RuntimeException)
200 return m_LogThread;
203 ::sal_Bool CsvFormatter::getLogTimestamp() throw (RuntimeException)
205 return m_LogTimestamp;
208 ::sal_Bool CsvFormatter::getLogSource() throw (RuntimeException)
210 return m_LogSource;
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;
247 if(m_LogEventNo)
248 buf.appendAscii("event no,");
249 if(m_LogThread)
250 buf.appendAscii("thread,");
251 if(m_LogTimestamp)
252 buf.appendAscii("timestamp,");
253 if(m_LogSource)
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;
270 if(m_LogEventNo)
272 aLogEntry.append( record.SequenceNumber );
273 aLogEntry.append(comma_char);
276 if(m_LogThread)
278 aLogEntry.append( record.ThreadID );
279 aLogEntry.append(comma_char);
282 if(m_LogTimestamp)
284 // ISO 8601
285 char buffer[ 30 ];
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);
299 if(m_LogSource)
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
311 // to be encoded
312 if(m_MultiColumn)
313 aLogEntry.append(record.Message);
314 else
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();
344 ++pServiceNames
346 if ( service_name == *pServiceNames )
347 return sal_True;
348 return sal_False;
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