merge the formfield patch from ooo-build
[ooovba.git] / extensions / source / logging / csvformatter.cxx
blob87ffbac7b494b5a423c07328629bb7d03e7dd511
1 /*************************************************************************
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * Copyright 2008 by Sun Microsystems, Inc.
6 * OpenOffice.org - a multi-platform office productivity suite
8 * $RCSfile: csvformatter.cxx,v $
10 * $Revision: 1.2 $
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"
35 #include <stdio.h>
36 #include <string>
38 /** === begin UNO includes === **/
39 #ifndef _COM_SUN_STAR_LOGGING_XLOGFORMATTER_HPP_
40 #include <com/sun/star/logging/XCsvLogFormatter.hpp>
41 #endif
42 #ifndef _COM_SUN_STAR_LOGGING_XLOGFORMATTER_HPP_
43 #include <com/sun/star/logging/XLogFormatter.hpp>
44 #endif
45 #ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
46 #include <com/sun/star/uno/XComponentContext.hpp>
47 #endif
48 #ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
49 #include <com/sun/star/lang/XServiceInfo.hpp>
50 #endif
51 /** === end UNO includes === **/
53 #include <comphelper/componentcontext.hxx>
55 #include <cppuhelper/implbase2.hxx>
57 #include <rtl/ustrbuf.hxx>
59 #include <osl/thread.h>
61 namespace logging
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
79 , XServiceInfo
80 > CsvFormatter_Base;
81 class CsvFormatter : public CsvFormatter_Base
83 public:
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 );
91 protected:
92 CsvFormatter( const Reference< XComponentContext >& context );
93 virtual ~CsvFormatter();
95 // XCsvLogFormatter
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);
108 // XLogFormatter
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);
113 // XServiceInfo
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);
118 private:
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
129 //= private helpers
130 namespace
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)
142 return true;
143 return false;
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();
154 buf.append(str);
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);
163 if(i!=-1)
164 buf.insert(buf_offset + i, quote_char);
166 buf.append(quote_char);
168 else
169 buf.append(str);
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"));
176 return result;
180 //= CsvFormatter - implementation
181 namespace logging
183 CsvFormatter::CsvFormatter( const Reference< XComponentContext >& context )
184 :m_aContext( context ),
185 m_LogEventNo(true),
186 m_LogThread(true),
187 m_LogTimestamp(true),
188 m_LogSource(false),
189 m_MultiColumn(false),
190 m_Columnnames(initialColumns())
193 CsvFormatter::~CsvFormatter()
196 ::sal_Bool CsvFormatter::getLogEventNo() throw (RuntimeException)
198 return m_LogEventNo;
201 ::sal_Bool CsvFormatter::getLogThread() throw (RuntimeException)
203 return m_LogThread;
206 ::sal_Bool CsvFormatter::getLogTimestamp() throw (RuntimeException)
208 return m_LogTimestamp;
211 ::sal_Bool CsvFormatter::getLogSource() throw (RuntimeException)
213 return m_LogSource;
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;
250 if(m_LogEventNo)
251 buf.appendAscii("event no,");
252 if(m_LogThread)
253 buf.appendAscii("thread,");
254 if(m_LogTimestamp)
255 buf.appendAscii("timestamp,");
256 if(m_LogSource)
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;
273 if(m_LogEventNo)
275 aLogEntry.append( record.SequenceNumber );
276 aLogEntry.append(comma_char);
279 if(m_LogThread)
281 aLogEntry.append( record.ThreadID );
282 aLogEntry.append(comma_char);
285 if(m_LogTimestamp)
287 // ISO 8601
288 char buffer[ 30 ];
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);
302 if(m_LogSource)
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
314 // to be encoded
315 if(m_MultiColumn)
316 aLogEntry.append(record.Message);
317 else
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();
347 ++pServiceNames
349 if ( service_name == *pServiceNames )
350 return sal_True;
351 return sal_False;
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