1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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>
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
56 class CsvFormatter
: public CsvFormatter_Base
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
);
68 virtual ~CsvFormatter();
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
;
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
;
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
;
99 ::com::sun::star::uno::Sequence
< OUString
> m_Columnnames
;
101 } // namespace logging
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)
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();
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
);
138 buf
.insert(buf_offset
+ i
, quote_char
);
140 buf
.append(quote_char
);
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";
156 CsvFormatter::CsvFormatter()
159 m_LogTimestamp(true),
161 m_MultiColumn(false),
162 m_Columnnames(initialColumns())
165 CsvFormatter::~CsvFormatter()
168 sal_Bool
CsvFormatter::getLogEventNo() throw (RuntimeException
, std::exception
)
173 sal_Bool
CsvFormatter::getLogThread() throw (RuntimeException
, std::exception
)
178 sal_Bool
CsvFormatter::getLogTimestamp() throw (RuntimeException
, std::exception
)
180 return m_LogTimestamp
;
183 sal_Bool
CsvFormatter::getLogSource() throw (RuntimeException
, std::exception
)
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
)
223 buf
.appendAscii("event no,");
225 buf
.appendAscii("thread,");
227 buf
.appendAscii("timestamp,");
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
;
247 aLogEntry
.append( record
.SequenceNumber
);
248 aLogEntry
.append(comma_char
);
253 aLogEntry
.append( record
.ThreadID
);
254 aLogEntry
.append(comma_char
);
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
);
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
288 aLogEntry
.append(record
.Message
);
290 appendEncodedString(aLogEntry
, record
.Message
);
292 aLogEntry
.append( dos_newline
);
293 return aLogEntry
.makeStringAndClear();
296 OUString SAL_CALL
CsvFormatter::getTail( ) throw (RuntimeException
, std::exception
)
301 OUString SAL_CALL
CsvFormatter::formatMultiColumn(const Sequence
< OUString
>& column_data
) throw (RuntimeException
, std::exception
)
303 sal_Int32 columns
= column_data
.getLength();
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: */