bump product version to 5.0.4.1
[LibreOffice.git] / extensions / source / logging / csvformatter.cxx
blob12c82dd8564b40ba943fd6bb44c62a36354d881a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "log_module.hxx"
22 #include "log_services.hxx"
24 #include <stdio.h>
25 #include <string>
27 #include <com/sun/star/logging/XCsvLogFormatter.hpp>
28 #include <com/sun/star/logging/XLogFormatter.hpp>
29 #include <com/sun/star/uno/XComponentContext.hpp>
30 #include <com/sun/star/lang/XServiceInfo.hpp>
32 #include <cppuhelper/implbase2.hxx>
33 #include <cppuhelper/supportsservice.hxx>
35 #include <rtl/ustrbuf.hxx>
37 #include <osl/thread.h>
39 namespace logging
42 using ::com::sun::star::logging::XCsvLogFormatter;
43 using ::com::sun::star::logging::XLogFormatter;
44 using ::com::sun::star::uno::XComponentContext;
45 using ::com::sun::star::uno::Reference;
46 using ::com::sun::star::uno::Sequence;
47 using ::com::sun::star::lang::XServiceInfo;
48 using ::com::sun::star::uno::RuntimeException;
49 using ::com::sun::star::logging::LogRecord;
50 using ::com::sun::star::uno::XInterface;
52 // formats for csv files as defined by RFC4180
53 typedef ::cppu::WeakImplHelper2 < XCsvLogFormatter
54 , XServiceInfo
55 > CsvFormatter_Base;
56 class CsvFormatter : public CsvFormatter_Base
58 public:
59 virtual OUString SAL_CALL formatMultiColumn(const Sequence< OUString>& column_data) throw (RuntimeException, std::exception) SAL_OVERRIDE;
61 // XServiceInfo - static version
62 static OUString SAL_CALL getImplementationName_static();
63 static Sequence< OUString > SAL_CALL getSupportedServiceNames_static();
64 static Reference< XInterface > Create( const Reference< XComponentContext >& context );
66 protected:
67 CsvFormatter();
68 virtual ~CsvFormatter();
70 // XCsvLogFormatter
71 virtual sal_Bool SAL_CALL getLogEventNo() throw (RuntimeException, std::exception) SAL_OVERRIDE;
72 virtual sal_Bool SAL_CALL getLogThread() throw (RuntimeException, std::exception) SAL_OVERRIDE;
73 virtual sal_Bool SAL_CALL getLogTimestamp() throw (RuntimeException, std::exception) SAL_OVERRIDE;
74 virtual sal_Bool SAL_CALL getLogSource() throw (RuntimeException, std::exception) SAL_OVERRIDE;
75 virtual Sequence< OUString > SAL_CALL getColumnnames() throw (RuntimeException, std::exception) SAL_OVERRIDE;
77 virtual void SAL_CALL setLogEventNo( sal_Bool log_event_no ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
78 virtual void SAL_CALL setLogThread( sal_Bool log_thread ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
79 virtual void SAL_CALL setLogTimestamp( sal_Bool log_timestamp ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
80 virtual void SAL_CALL setLogSource( sal_Bool log_source ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
81 virtual void SAL_CALL setColumnnames( const Sequence< OUString>& column_names) throw (RuntimeException, std::exception) SAL_OVERRIDE;
83 // XLogFormatter
84 virtual OUString SAL_CALL getHead( ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
85 virtual OUString SAL_CALL format( const LogRecord& Record ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
86 virtual OUString SAL_CALL getTail( ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
88 // XServiceInfo
89 virtual OUString SAL_CALL getImplementationName() throw(RuntimeException, std::exception) SAL_OVERRIDE;
90 virtual sal_Bool SAL_CALL supportsService( const OUString& service_name ) throw(RuntimeException, std::exception) SAL_OVERRIDE;
91 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(RuntimeException, std::exception) SAL_OVERRIDE;
93 private:
94 bool m_LogEventNo;
95 bool m_LogThread;
96 bool m_LogTimestamp;
97 bool m_LogSource;
98 bool m_MultiColumn;
99 ::com::sun::star::uno::Sequence< OUString > m_Columnnames;
101 } // namespace logging
103 // private helpers
104 namespace
106 const sal_Unicode quote_char = '"';
107 const sal_Unicode comma_char = ',';
108 const OUString dos_newline = "\r\n";
110 inline bool needsQuoting(const OUString& str)
112 static const OUString quote_trigger_chars = "\",\n\r";
113 sal_Int32 len = str.getLength();
114 for(sal_Int32 i=0; i<len; i++)
115 if(quote_trigger_chars.indexOf(str[i])!=-1)
116 return true;
117 return false;
120 inline void appendEncodedString(OUStringBuffer& buf, const OUString& str)
122 if(needsQuoting(str))
124 // each double-quote will get replaced by two double-quotes
125 buf.append(quote_char);
126 const sal_Int32 buf_offset = buf.getLength();
127 const sal_Int32 str_length = str.getLength();
128 buf.append(str);
129 // special treatment for the last character
130 if(quote_char==str[str_length-1])
131 buf.append(quote_char);
132 // iterating backwards because the index at which we insert wont be shifted
133 // when moving that way.
134 for(sal_Int32 i = str_length; i>=0; )
136 i=str.lastIndexOf(quote_char, --i);
137 if(i!=-1)
138 buf.insert(buf_offset + i, quote_char);
140 buf.append(quote_char);
142 else
143 buf.append(str);
146 ::com::sun::star::uno::Sequence< OUString> initialColumns()
148 com::sun::star::uno::Sequence< OUString> result = ::com::sun::star::uno::Sequence< OUString>(1);
149 result[0] = "message";
150 return result;
154 namespace logging
156 CsvFormatter::CsvFormatter()
157 :m_LogEventNo(true),
158 m_LogThread(true),
159 m_LogTimestamp(true),
160 m_LogSource(false),
161 m_MultiColumn(false),
162 m_Columnnames(initialColumns())
165 CsvFormatter::~CsvFormatter()
168 sal_Bool CsvFormatter::getLogEventNo() throw (RuntimeException, std::exception)
170 return m_LogEventNo;
173 sal_Bool CsvFormatter::getLogThread() throw (RuntimeException, std::exception)
175 return m_LogThread;
178 sal_Bool CsvFormatter::getLogTimestamp() throw (RuntimeException, std::exception)
180 return m_LogTimestamp;
183 sal_Bool CsvFormatter::getLogSource() throw (RuntimeException, std::exception)
185 return m_LogSource;
188 Sequence< OUString > CsvFormatter::getColumnnames() throw (RuntimeException, std::exception)
190 return m_Columnnames;
193 void CsvFormatter::setLogEventNo(sal_Bool log_event_no) throw (RuntimeException, std::exception)
195 m_LogEventNo = log_event_no;
198 void CsvFormatter::setLogThread(sal_Bool log_thread) throw (RuntimeException, std::exception)
200 m_LogThread = log_thread;
203 void CsvFormatter::setLogTimestamp(sal_Bool log_timestamp) throw (RuntimeException, std::exception)
205 m_LogTimestamp = log_timestamp;
208 void CsvFormatter::setLogSource(sal_Bool log_source) throw (RuntimeException, std::exception)
210 m_LogSource = log_source;
213 void CsvFormatter::setColumnnames(const Sequence< OUString >& columnnames) throw (RuntimeException, std::exception)
215 m_Columnnames = Sequence< OUString>(columnnames);
216 m_MultiColumn = (m_Columnnames.getLength()>1);
219 OUString SAL_CALL CsvFormatter::getHead( ) throw (RuntimeException, std::exception)
221 OUStringBuffer buf;
222 if(m_LogEventNo)
223 buf.appendAscii("event no,");
224 if(m_LogThread)
225 buf.appendAscii("thread,");
226 if(m_LogTimestamp)
227 buf.appendAscii("timestamp,");
228 if(m_LogSource)
229 buf.appendAscii("class,method,");
230 sal_Int32 columns = m_Columnnames.getLength();
231 for(sal_Int32 i=0; i<columns; i++)
233 buf.append(m_Columnnames[i]);
234 buf.append(comma_char);
236 buf.setLength(buf.getLength()-1);
237 buf.append(dos_newline);
238 return buf.makeStringAndClear();
241 OUString SAL_CALL CsvFormatter::format( const LogRecord& record ) throw (RuntimeException, std::exception)
243 OUStringBuffer aLogEntry;
245 if(m_LogEventNo)
247 aLogEntry.append( record.SequenceNumber );
248 aLogEntry.append(comma_char);
251 if(m_LogThread)
253 aLogEntry.append( record.ThreadID );
254 aLogEntry.append(comma_char);
257 if(m_LogTimestamp)
259 // ISO 8601
260 char buffer[ 30 ];
261 const size_t buffer_size = sizeof( buffer );
262 snprintf( buffer, buffer_size, "%04i-%02i-%02iT%02i:%02i:%02i.%09i",
263 (int)record.LogTime.Year,
264 (int)record.LogTime.Month,
265 (int)record.LogTime.Day,
266 (int)record.LogTime.Hours,
267 (int)record.LogTime.Minutes,
268 (int)record.LogTime.Seconds,
269 (int)record.LogTime.NanoSeconds );
270 aLogEntry.appendAscii( buffer );
271 aLogEntry.append(comma_char);
274 if(m_LogSource)
276 appendEncodedString(aLogEntry, record.SourceClassName);
277 aLogEntry.append(comma_char);
279 appendEncodedString(aLogEntry, record.SourceMethodName);
280 aLogEntry.append(comma_char);
283 // if the CsvFormatter has multiple columns set via setColumnnames(), the
284 // message of the record is expected to be encoded with formatMultiColumn
285 // if the CsvFormatter has only one column set, the message is expected not
286 // to be encoded
287 if(m_MultiColumn)
288 aLogEntry.append(record.Message);
289 else
290 appendEncodedString(aLogEntry, record.Message);
292 aLogEntry.append( dos_newline );
293 return aLogEntry.makeStringAndClear();
296 OUString SAL_CALL CsvFormatter::getTail( ) throw (RuntimeException, std::exception)
298 return OUString();
301 OUString SAL_CALL CsvFormatter::formatMultiColumn(const Sequence< OUString>& column_data) throw (RuntimeException, std::exception)
303 sal_Int32 columns = column_data.getLength();
304 OUStringBuffer buf;
305 for(int i=0; i<columns; i++)
307 appendEncodedString(buf, column_data[i]);
308 buf.append(comma_char);
310 buf.setLength(buf.getLength()-1);
311 return buf.makeStringAndClear();
314 sal_Bool SAL_CALL CsvFormatter::supportsService( const OUString& service_name ) throw(RuntimeException, std::exception)
316 return cppu::supportsService(this, service_name);
319 OUString SAL_CALL CsvFormatter::getImplementationName() throw(RuntimeException, std::exception)
321 return getImplementationName_static();
324 Sequence< OUString > SAL_CALL CsvFormatter::getSupportedServiceNames() throw(RuntimeException, std::exception)
326 return getSupportedServiceNames_static();
329 OUString SAL_CALL CsvFormatter::getImplementationName_static()
331 return OUString( "com.sun.star.comp.extensions.CsvFormatter" );
334 Sequence< OUString > SAL_CALL CsvFormatter::getSupportedServiceNames_static()
336 Sequence< OUString > aServiceNames(1);
337 aServiceNames[0] = "com.sun.star.logging.CsvFormatter";
338 return aServiceNames;
341 Reference< XInterface > CsvFormatter::Create( const Reference< XComponentContext >& )
343 return *( new CsvFormatter );
346 void createRegistryInfo_CsvFormatter()
348 static OAutoRegistration< CsvFormatter > aAutoRegistration;
350 } // namespace logging
352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */