1 /************************************************************************* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * Copyright 2000, 2010 Oracle and/or its affiliates. 5 * 6 * OpenOffice.org - a multi-platform office productivity suite 7 * 8 * This file is part of OpenOffice.org. 9 * 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. 13 * 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). 19 * 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. 24 * 25 ***********************************************************************/ 26 27 // MARKER(update_precomp.py): autogen include statement, do not remove 28 #include "precompiled_comphelper.hxx" 29 30 #include <comphelper/uieventslogger.hxx> 31 #include <boost/shared_ptr.hpp> 32 #include <com/sun/star/frame/XDesktop.hpp> 33 #include <com/sun/star/frame/XTerminateListener.hpp> 34 #include <com/sun/star/lang/XEventListener.hpp> 35 #include <com/sun/star/lang/XMultiComponentFactory.hpp> 36 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 37 #include <com/sun/star/logging/LogLevel.hpp> 38 #include <com/sun/star/logging/XCsvLogFormatter.hpp> 39 #include <com/sun/star/logging/XLogHandler.hpp> 40 #include <com/sun/star/logging/XLogger.hpp> 41 #include <com/sun/star/logging/XLoggerPool.hpp> 42 #include <com/sun/star/oooimprovement/XCoreController.hpp> 43 #include <com/sun/star/uno/Sequence.hxx> 44 #include <com/sun/star/util/XStringSubstitution.hpp> 45 #include <comphelper/configurationhelper.hxx> 46 #include <comphelper/processfactory.hxx> 47 #include <map> 48 #include <osl/file.hxx> 49 #include <osl/mutex.hxx> 50 #include <osl/time.h> 51 #include <rtl/ustrbuf.hxx> 52 53 54 using namespace com::sun::star::beans; 55 using namespace com::sun::star::frame; 56 using namespace com::sun::star::lang; 57 using namespace com::sun::star::logging; 58 using namespace com::sun::star::oooimprovement; 59 using namespace com::sun::star::uno; 60 using namespace com::sun::star::util; 61 using namespace cppu; 62 using namespace osl; 63 using namespace rtl; 64 using namespace std; 65 66 67 namespace 68 { 69 static void lcl_SetupOriginAppAbbr(map<OUString, OUString>& abbrs) 70 { 71 abbrs[OUString::createFromAscii("com.sun.star.text.TextDocument")] = OUString::createFromAscii("W"); // Writer 72 abbrs[OUString::createFromAscii("com.sun.star.sheet.SpreadsheetDocument")] = OUString::createFromAscii("C"); // Calc 73 abbrs[OUString::createFromAscii("com.sun.star.presentation.PresentationDocument")] = OUString::createFromAscii("I"); // Impress 74 abbrs[OUString::createFromAscii("com.sun.star.drawing.DrawingDocument")] = OUString::createFromAscii("D"); // Draw 75 }; 76 77 static void lcl_SetupOriginWidgetAbbr(map<OUString,OUString>& abbrs) 78 { 79 abbrs[OUString::createFromAscii("ButtonToolbarController")] = OUString::createFromAscii("0"); 80 abbrs[OUString::createFromAscii("ComplexToolbarController")] = OUString::createFromAscii("1"); 81 abbrs[OUString::createFromAscii("ControlMenuController")] = OUString::createFromAscii("2"); 82 abbrs[OUString::createFromAscii("FontMenuController")] = OUString::createFromAscii("3"); 83 abbrs[OUString::createFromAscii("FontSizeMenuController")] = OUString::createFromAscii("4"); 84 abbrs[OUString::createFromAscii("FooterMenuController")] = OUString::createFromAscii("5"); 85 abbrs[OUString::createFromAscii("GenericToolbarController")] = OUString::createFromAscii("6"); 86 abbrs[OUString::createFromAscii("HeaderMenuController")] = OUString::createFromAscii("7"); 87 abbrs[OUString::createFromAscii("LanguageSelectionMenuController")] = OUString::createFromAscii("8"); 88 abbrs[OUString::createFromAscii("LangSelectionStatusbarController")] = OUString::createFromAscii("9"); 89 abbrs[OUString::createFromAscii("MacrosMenuController")] = OUString::createFromAscii("10"); 90 abbrs[OUString::createFromAscii("MenuBarManager")] = OUString::createFromAscii("11"); 91 abbrs[OUString::createFromAscii("NewMenuController")] = OUString::createFromAscii("12"); 92 abbrs[OUString::createFromAscii("ObjectMenuController")] = OUString::createFromAscii("13"); 93 abbrs[OUString::createFromAscii("RecentFilesMenuController")] = OUString::createFromAscii("14"); 94 abbrs[OUString::createFromAscii("ToolbarsMenuController")] = OUString::createFromAscii("15"); 95 abbrs[OUString::createFromAscii("SfxToolBoxControl")] = OUString::createFromAscii("16"); 96 abbrs[OUString::createFromAscii("SfxAsyncExec")] = OUString::createFromAscii("17"); 97 abbrs[OUString::createFromAscii("AcceleratorExecute")] = OUString::createFromAscii("18"); 98 }; 99 } 100 101 namespace comphelper 102 { 103 // declaration of implementation 104 class UiEventsLogger_Impl; 105 class UiEventsLogger_Impl : public UiEventsLogger 106 { 107 private: 108 //typedefs and friends 109 friend class UiEventsLogger; 110 typedef UiEventsLogger_Impl* ptr; 111 112 // instance methods and data 113 UiEventsLogger_Impl(); 114 void initializeLogger(); 115 void logDispatch(const ::com::sun::star::util::URL& url, 116 const Sequence<PropertyValue>& args); 117 void logRotated(); 118 void logVcl(const ::rtl::OUString& parent_id, 119 sal_Int32 window_type, 120 const ::rtl::OUString& id, 121 const ::rtl::OUString& method, 122 const ::rtl::OUString& param); 123 void rotate(); 124 void hotRotate(); 125 void prepareLogHandler(); 126 void checkIdleTimeout(); 127 OUString getCurrentPath(); 128 OUString getRotatedPath(); 129 void disposing(); 130 131 bool m_Active; 132 TimeValue m_LastLogEventTime; 133 const OUString m_LogPath; 134 const TimeValue m_IdleTimeout; 135 sal_Int32 m_SessionLogEventCount; 136 Reference<XLogger> m_Logger; 137 Reference<XLogHandler> m_LogHandler; 138 Reference<XCsvLogFormatter> m_Formatter; 139 map<OUString, OUString> m_OriginAppAbbr; 140 map<OUString, OUString> m_OriginWidgetAbbr; 141 142 143 // static methods and data 144 static ptr getInstance(); 145 static void prepareMutex(); 146 static bool shouldActivate(); 147 static bool getEnabledFromCoreController(); 148 static bool getEnabledFromCfg(); 149 static TimeValue getIdleTimeoutFromCfg(); 150 static OUString getLogPathFromCfg(); 151 static sal_Int32 findIdx(const Sequence<PropertyValue>& args, const OUString& key); 152 153 static ptr instance; 154 static Mutex * singleton_mutex; 155 static const sal_Int32 COLUMNS; 156 static const OUString CFG_ENABLED; 157 static const OUString CFG_IDLETIMEOUT; 158 static const OUString CFG_LOGGING; 159 static const OUString CFG_LOGPATH; 160 static const OUString CFG_OOOIMPROVEMENT; 161 static const OUString ETYPE_DISPATCH; 162 static const OUString ETYPE_ROTATED; 163 static const OUString ETYPE_VCL; 164 static const OUString CSSL_CSVFORMATTER; 165 static const OUString CSSL_FILEHANDLER; 166 static const OUString CSSL_LOGGERPOOL; 167 static const OUString CSSO_CORECONTROLLER; 168 static const OUString CSST_JOBEXECUTOR; 169 static const OUString CSSU_PATHSUB; 170 static const OUString LOGGERNAME; 171 static const OUString LOGORIGINAPP; 172 static const OUString LOGORIGINWIDGET; 173 static const OUString UNKNOWN_ORIGIN; 174 static const OUString FN_CURRENTLOG; 175 static const OUString FN_ROTATEDLOG; 176 static const OUString LOGROTATE_EVENTNAME; 177 static const OUString URL_UNO; 178 static const OUString URL_SPECIAL; 179 static const OUString URL_FILE; 180 }; 181 } 182 183 namespace comphelper 184 { 185 // consts 186 const sal_Int32 UiEventsLogger_Impl::COLUMNS = 9; 187 const OUString UiEventsLogger_Impl::CFG_ENABLED = OUString::createFromAscii("EnablingAllowed"); 188 const OUString UiEventsLogger_Impl::CFG_IDLETIMEOUT = OUString::createFromAscii("IdleTimeout"); 189 const OUString UiEventsLogger_Impl::CFG_LOGGING = OUString::createFromAscii("/org.openoffice.Office.Logging"); 190 const OUString UiEventsLogger_Impl::CFG_LOGPATH = OUString::createFromAscii("LogPath"); 191 const OUString UiEventsLogger_Impl::CFG_OOOIMPROVEMENT = OUString::createFromAscii("OOoImprovement"); 192 193 const OUString UiEventsLogger_Impl::CSSL_CSVFORMATTER = OUString::createFromAscii("com.sun.star.logging.CsvFormatter"); 194 const OUString UiEventsLogger_Impl::CSSL_FILEHANDLER = OUString::createFromAscii("com.sun.star.logging.FileHandler"); 195 const OUString UiEventsLogger_Impl::CSSL_LOGGERPOOL = OUString::createFromAscii("com.sun.star.logging.LoggerPool"); 196 const OUString UiEventsLogger_Impl::CSSO_CORECONTROLLER = OUString::createFromAscii("com.sun.star.oooimprovement.CoreController"); 197 const OUString UiEventsLogger_Impl::CSSU_PATHSUB = OUString::createFromAscii("com.sun.star.util.PathSubstitution"); 198 199 const OUString UiEventsLogger_Impl::ETYPE_DISPATCH = OUString::createFromAscii("dispatch"); 200 const OUString UiEventsLogger_Impl::ETYPE_ROTATED = OUString::createFromAscii("rotated"); 201 const OUString UiEventsLogger_Impl::ETYPE_VCL = OUString::createFromAscii("vcl"); 202 203 const OUString UiEventsLogger_Impl::LOGGERNAME = OUString::createFromAscii("org.openoffice.oooimprovement.Core.UiEventsLogger"); 204 const OUString UiEventsLogger_Impl::LOGORIGINWIDGET = OUString::createFromAscii("comphelper.UiEventsLogger.LogOriginWidget"); 205 const OUString UiEventsLogger_Impl::LOGORIGINAPP = OUString::createFromAscii("comphelper.UiEventsLogger.LogOriginApp"); 206 207 const OUString UiEventsLogger_Impl::UNKNOWN_ORIGIN = OUString::createFromAscii("unknown origin"); 208 const OUString UiEventsLogger_Impl::FN_CURRENTLOG = OUString::createFromAscii("Current"); 209 const OUString UiEventsLogger_Impl::FN_ROTATEDLOG = OUString::createFromAscii("OOoImprove"); 210 const OUString UiEventsLogger_Impl::LOGROTATE_EVENTNAME = OUString::createFromAscii("onOOoImprovementLogRotated"); 211 212 const OUString UiEventsLogger_Impl::URL_UNO = OUString::createFromAscii(".uno:"); 213 const OUString UiEventsLogger_Impl::URL_SPECIAL = OUString::createFromAscii(".special:"); 214 const OUString UiEventsLogger_Impl::URL_FILE = OUString::createFromAscii("file:"); 215 216 217 // public UiEventsLogger interface 218 sal_Bool UiEventsLogger::isEnabled() 219 { 220 if ( UiEventsLogger_Impl::getEnabledFromCfg() ) 221 { 222 try { 223 UiEventsLogger_Impl::prepareMutex(); 224 Guard<Mutex> singleton_guard(UiEventsLogger_Impl::singleton_mutex); 225 return UiEventsLogger_Impl::getInstance()->m_Active; 226 } catch(...) { return false; } // never throws 227 } // if ( ) 228 return sal_False; 229 } 230 231 sal_Int32 UiEventsLogger::getSessionLogEventCount() 232 { 233 try { 234 UiEventsLogger_Impl::prepareMutex(); 235 Guard<Mutex> singleton_guard(UiEventsLogger_Impl::singleton_mutex); 236 return UiEventsLogger_Impl::getInstance()->m_SessionLogEventCount; 237 } catch(...) { return 0; } // never throws 238 } 239 240 void UiEventsLogger::appendDispatchOrigin( 241 Sequence<PropertyValue>& args, 242 const OUString& originapp, 243 const OUString& originwidget) 244 { 245 sal_Int32 old_length = args.getLength(); 246 args.realloc(old_length+2); 247 args[old_length].Name = UiEventsLogger_Impl::LOGORIGINAPP; 248 args[old_length].Value = static_cast<Any>(originapp); 249 args[old_length+1].Name = UiEventsLogger_Impl::LOGORIGINWIDGET; 250 args[old_length+1].Value = static_cast<Any>(originwidget); 251 } 252 253 Sequence<PropertyValue> UiEventsLogger::purgeDispatchOrigin( 254 const Sequence<PropertyValue>& args) 255 { 256 Sequence<PropertyValue> result(args.getLength()); 257 sal_Int32 target_idx=0; 258 for(sal_Int32 source_idx=0; source_idx<args.getLength(); source_idx++) 259 if(args[source_idx].Name != UiEventsLogger_Impl::LOGORIGINAPP 260 && args[source_idx].Name != UiEventsLogger_Impl::LOGORIGINWIDGET) 261 result[target_idx++] = args[source_idx]; 262 result.realloc(target_idx); 263 return result; 264 } 265 266 void UiEventsLogger::logDispatch( 267 const URL& url, 268 const Sequence<PropertyValue>& args) 269 { 270 try { 271 UiEventsLogger_Impl::prepareMutex(); 272 Guard<Mutex> singleton_guard(UiEventsLogger_Impl::singleton_mutex); 273 UiEventsLogger_Impl::getInstance()->logDispatch(url, args); 274 } catch(...) { } // never throws 275 } 276 277 void UiEventsLogger::logVcl( 278 const OUString& parent_id, 279 sal_Int32 window_type, 280 const OUString& id, 281 const OUString& method, 282 const OUString& param) 283 { 284 try { 285 UiEventsLogger_Impl::prepareMutex(); 286 Guard<Mutex> singleton_guard(UiEventsLogger_Impl::singleton_mutex); 287 UiEventsLogger_Impl::getInstance()->logVcl(parent_id, window_type, id, method, param); 288 } catch(...) { } // never throws 289 } 290 291 void UiEventsLogger::logVcl( 292 const OUString& parent_id, 293 sal_Int32 window_type, 294 const OUString& id, 295 const OUString& method, 296 sal_Int32 param) 297 { 298 OUStringBuffer buf; 299 UiEventsLogger::logVcl(parent_id, window_type, id, method, buf.append(param).makeStringAndClear()); 300 } 301 302 void UiEventsLogger::logVcl( 303 const OUString& parent_id, 304 sal_Int32 window_type, 305 const OUString& id, 306 const OUString& method) 307 { 308 OUString empty; 309 UiEventsLogger::logVcl(parent_id, window_type, id, method, empty); 310 } 311 312 void UiEventsLogger::disposing() 313 { 314 // we dont want to create an instance just to dispose it 315 UiEventsLogger_Impl::prepareMutex(); 316 Guard<Mutex> singleton_guard(UiEventsLogger_Impl::singleton_mutex); 317 if(UiEventsLogger_Impl::instance!=UiEventsLogger_Impl::ptr()) 318 UiEventsLogger_Impl::getInstance()->disposing(); 319 } 320 321 void UiEventsLogger::reinit() 322 { 323 UiEventsLogger_Impl::prepareMutex(); 324 Guard<Mutex> singleton_guard(UiEventsLogger_Impl::singleton_mutex); 325 if(UiEventsLogger_Impl::instance) 326 { 327 UiEventsLogger_Impl::instance->disposing(); 328 delete UiEventsLogger_Impl::instance; 329 UiEventsLogger_Impl::instance = NULL; 330 } 331 } 332 333 // private UiEventsLogger_Impl methods 334 UiEventsLogger_Impl::UiEventsLogger_Impl() 335 : m_Active(UiEventsLogger_Impl::shouldActivate()) 336 , m_LogPath(UiEventsLogger_Impl::getLogPathFromCfg()) 337 , m_IdleTimeout(UiEventsLogger_Impl::getIdleTimeoutFromCfg()) 338 , m_SessionLogEventCount(0) 339 { 340 lcl_SetupOriginAppAbbr(m_OriginAppAbbr); 341 lcl_SetupOriginWidgetAbbr(m_OriginWidgetAbbr); 342 m_LastLogEventTime.Seconds = m_LastLogEventTime.Nanosec = 0; 343 if(m_Active) rotate(); 344 if(m_Active) initializeLogger(); 345 } 346 347 void UiEventsLogger_Impl::logDispatch( 348 const URL& url, 349 const Sequence<PropertyValue>& args) 350 { 351 if(!m_Active) return; 352 if(!url.Complete.match(URL_UNO) 353 && !url.Complete.match(URL_FILE) 354 && !url.Complete.match(URL_SPECIAL)) 355 { 356 return; 357 } 358 checkIdleTimeout(); 359 360 Sequence<OUString> logdata = Sequence<OUString>(COLUMNS); 361 logdata[0] = ETYPE_DISPATCH; 362 sal_Int32 originapp_idx = findIdx(args, LOGORIGINAPP); 363 if(originapp_idx!=-1) 364 { 365 OUString app; 366 args[originapp_idx].Value >>= app; 367 map<OUString, OUString>::iterator abbr_it = m_OriginAppAbbr.find(app); 368 if(abbr_it != m_OriginAppAbbr.end()) 369 app = abbr_it->second; 370 logdata[1] = app; 371 } 372 else 373 logdata[1] = UNKNOWN_ORIGIN; 374 sal_Int32 originwidget_idx = findIdx(args, LOGORIGINWIDGET); 375 if(originwidget_idx!=-1) 376 { 377 OUString widget; 378 args[originwidget_idx].Value >>= widget; 379 map<OUString, OUString>::iterator widget_it = m_OriginWidgetAbbr.find(widget); 380 if(widget_it != m_OriginWidgetAbbr.end()) 381 widget = widget_it->second; 382 logdata[2] = widget; 383 } 384 else 385 logdata[2] = UNKNOWN_ORIGIN; 386 if(url.Complete.match(URL_FILE)) 387 logdata[3] = URL_FILE; 388 else 389 logdata[3] = url.Main; 390 OSL_TRACE("UiEventsLogger Logging: %s,%s,%s,%s,%s,%s,%s,%s", 391 OUStringToOString(logdata[0],RTL_TEXTENCODING_UTF8).getStr(), 392 OUStringToOString(logdata[1],RTL_TEXTENCODING_UTF8).getStr(), 393 OUStringToOString(logdata[2],RTL_TEXTENCODING_UTF8).getStr(), 394 OUStringToOString(logdata[3],RTL_TEXTENCODING_UTF8).getStr(), 395 OUStringToOString(logdata[4],RTL_TEXTENCODING_UTF8).getStr(), 396 OUStringToOString(logdata[5],RTL_TEXTENCODING_UTF8).getStr(), 397 OUStringToOString(logdata[6],RTL_TEXTENCODING_UTF8).getStr(), 398 OUStringToOString(logdata[7],RTL_TEXTENCODING_UTF8).getStr(), 399 OUStringToOString(logdata[8],RTL_TEXTENCODING_UTF8).getStr()); 400 m_Logger->log(LogLevel::INFO, m_Formatter->formatMultiColumn(logdata)); 401 m_SessionLogEventCount++; 402 } 403 404 void UiEventsLogger_Impl::logRotated() 405 { 406 Sequence<OUString> logdata = Sequence<OUString>(COLUMNS); 407 logdata[0] = ETYPE_ROTATED; 408 OSL_TRACE("UiEventsLogger Logging: %s,%s,%s,%s,%s,%s,%s,%s", 409 OUStringToOString(logdata[0],RTL_TEXTENCODING_UTF8).getStr(), 410 OUStringToOString(logdata[1],RTL_TEXTENCODING_UTF8).getStr(), 411 OUStringToOString(logdata[2],RTL_TEXTENCODING_UTF8).getStr(), 412 OUStringToOString(logdata[3],RTL_TEXTENCODING_UTF8).getStr(), 413 OUStringToOString(logdata[4],RTL_TEXTENCODING_UTF8).getStr(), 414 OUStringToOString(logdata[5],RTL_TEXTENCODING_UTF8).getStr(), 415 OUStringToOString(logdata[6],RTL_TEXTENCODING_UTF8).getStr(), 416 OUStringToOString(logdata[7],RTL_TEXTENCODING_UTF8).getStr(), 417 OUStringToOString(logdata[8],RTL_TEXTENCODING_UTF8).getStr()); 418 m_Logger->log(LogLevel::INFO, m_Formatter->formatMultiColumn(logdata)); 419 } 420 421 void UiEventsLogger_Impl::logVcl( 422 const OUString& parent_id, 423 sal_Int32 window_type, 424 const OUString& id, 425 const OUString& method, 426 const OUString& param) 427 { 428 if(!m_Active) return; 429 checkIdleTimeout(); 430 431 OUStringBuffer buf; 432 Sequence<OUString> logdata = Sequence<OUString>(COLUMNS); 433 logdata[0] = ETYPE_VCL; 434 logdata[4] = parent_id; 435 logdata[5] = buf.append(window_type).makeStringAndClear(); 436 logdata[6] = id; 437 logdata[7] = method; 438 logdata[8] = param; 439 OSL_TRACE("UiEventsLogger Logging: %s,%s,%s,%s,%s,%s,%s,%s", 440 OUStringToOString(logdata[0],RTL_TEXTENCODING_UTF8).getStr(), 441 OUStringToOString(logdata[1],RTL_TEXTENCODING_UTF8).getStr(), 442 OUStringToOString(logdata[2],RTL_TEXTENCODING_UTF8).getStr(), 443 OUStringToOString(logdata[3],RTL_TEXTENCODING_UTF8).getStr(), 444 OUStringToOString(logdata[4],RTL_TEXTENCODING_UTF8).getStr(), 445 OUStringToOString(logdata[5],RTL_TEXTENCODING_UTF8).getStr(), 446 OUStringToOString(logdata[6],RTL_TEXTENCODING_UTF8).getStr(), 447 OUStringToOString(logdata[7],RTL_TEXTENCODING_UTF8).getStr(), 448 OUStringToOString(logdata[8],RTL_TEXTENCODING_UTF8).getStr()); 449 m_Logger->log(LogLevel::INFO, m_Formatter->formatMultiColumn(logdata)); 450 m_SessionLogEventCount++; 451 } 452 453 void UiEventsLogger_Impl::rotate() 454 { 455 FileBase::RC result = File::move(getCurrentPath(), getRotatedPath()); 456 if(result!=FileBase::E_None && result!=FileBase::E_NOENT) 457 m_Active = false; 458 } 459 460 void UiEventsLogger_Impl::hotRotate() 461 { 462 logRotated(); 463 m_Logger->removeLogHandler(m_LogHandler); 464 m_LogHandler = NULL; 465 rotate(); 466 prepareLogHandler(); 467 if(m_Formatter.is() && m_LogHandler.is() && m_Logger.is()) 468 { 469 m_LogHandler->setFormatter(Reference<XLogFormatter>(m_Formatter, UNO_QUERY)); 470 m_LogHandler->setLevel(LogLevel::ALL); 471 m_Logger->addLogHandler(m_LogHandler); 472 } 473 else 474 m_Active = false; 475 } 476 477 void UiEventsLogger_Impl::prepareLogHandler() 478 { 479 Reference<XMultiServiceFactory> sm = getProcessServiceFactory(); 480 481 Sequence<Any> init_args = Sequence<Any>(1); 482 init_args[0] = static_cast<Any>(getCurrentPath()); 483 Reference< XInterface > temp = 484 sm->createInstanceWithArguments(CSSL_FILEHANDLER, init_args); 485 m_LogHandler = Reference<XLogHandler>(temp, UNO_QUERY); 486 } 487 488 void UiEventsLogger_Impl::checkIdleTimeout() 489 { 490 TimeValue now; 491 osl_getSystemTime(&now); 492 if(now.Seconds - m_LastLogEventTime.Seconds > m_IdleTimeout.Seconds && m_SessionLogEventCount>0) 493 hotRotate(); 494 m_LastLogEventTime = now; 495 } 496 497 OUString UiEventsLogger_Impl::getCurrentPath() 498 { 499 OUStringBuffer current_path(m_LogPath); 500 current_path.appendAscii("/"); 501 current_path.append(FN_CURRENTLOG); 502 current_path.appendAscii(".csv"); 503 return current_path.makeStringAndClear(); 504 } 505 506 OUString UiEventsLogger_Impl::getRotatedPath() 507 { 508 OUStringBuffer rotated_path(m_LogPath); 509 rotated_path.appendAscii("/"); 510 rotated_path.append(FN_ROTATEDLOG); 511 rotated_path.appendAscii("-"); 512 { 513 // ISO 8601 514 char tsrotated_pathfer[20]; 515 oslDateTime now; 516 TimeValue now_tv; 517 osl_getSystemTime(&now_tv); 518 osl_getDateTimeFromTimeValue(&now_tv, &now); 519 const size_t rotated_pathfer_size = sizeof(tsrotated_pathfer); 520 snprintf(tsrotated_pathfer, rotated_pathfer_size, "%04i-%02i-%02iT%02i_%02i_%02i", 521 now.Year, 522 now.Month, 523 now.Day, 524 now.Hours, 525 now.Minutes, 526 now.Seconds); 527 rotated_path.appendAscii(tsrotated_pathfer); 528 rotated_path.appendAscii(".csv"); 529 } 530 return rotated_path.makeStringAndClear(); 531 } 532 533 void UiEventsLogger_Impl::initializeLogger() 534 { 535 Reference<XMultiServiceFactory> sm = getProcessServiceFactory(); 536 537 // getting the Core Uno proxy object 538 // It will call disposing and make sure we clear all our references 539 { 540 Reference<XTerminateListener> xCore( 541 sm->createInstance(OUString::createFromAscii("com.sun.star.oooimprovement.Core")), 542 UNO_QUERY); 543 Reference<XDesktop> xDesktop( 544 sm->createInstance(OUString::createFromAscii("com.sun.star.frame.Desktop")), 545 UNO_QUERY); 546 if(!(xCore.is() && xDesktop.is())) 547 { 548 m_Active = false; 549 return; 550 } 551 xDesktop->addTerminateListener(xCore); 552 } 553 // getting the LoggerPool 554 Reference<XLoggerPool> pool; 555 { 556 Reference<XInterface> temp = 557 sm->createInstance(CSSL_LOGGERPOOL); 558 pool = Reference<XLoggerPool>(temp, UNO_QUERY); 559 } 560 561 // getting the Logger 562 m_Logger = pool->getNamedLogger(LOGGERNAME); 563 564 // getting the FileHandler 565 prepareLogHandler(); 566 567 // getting the Formatter 568 { 569 Reference<XInterface> temp = 570 sm->createInstance(CSSL_CSVFORMATTER); 571 m_Formatter = Reference<XCsvLogFormatter>(temp, UNO_QUERY); 572 } 573 574 if(m_Formatter.is() && m_LogHandler.is() && m_Logger.is()) 575 { 576 Sequence<OUString> columns = Sequence<OUString>(COLUMNS); 577 columns[0] = OUString::createFromAscii("eventtype"); 578 columns[1] = OUString::createFromAscii("originapp"); 579 columns[2] = OUString::createFromAscii("originwidget"); 580 columns[3] = OUString::createFromAscii("uno url"); 581 columns[4] = OUString::createFromAscii("parent id"); 582 columns[5] = OUString::createFromAscii("window type"); 583 columns[6] = OUString::createFromAscii("id"); 584 columns[7] = OUString::createFromAscii("method"); 585 columns[8] = OUString::createFromAscii("parameter"); 586 m_Formatter->setColumnnames(columns); 587 m_LogHandler->setFormatter(Reference<XLogFormatter>(m_Formatter, UNO_QUERY)); 588 m_Logger->setLevel(LogLevel::ALL); 589 m_LogHandler->setLevel(LogLevel::ALL); 590 m_Logger->addLogHandler(m_LogHandler); 591 } 592 else 593 m_Active = false; 594 } 595 596 // private static UiEventsLogger_Impl 597 bool UiEventsLogger_Impl::shouldActivate() 598 { 599 return getEnabledFromCfg() && getEnabledFromCoreController(); 600 } 601 602 OUString UiEventsLogger_Impl::getLogPathFromCfg() 603 { 604 OUString result; 605 Reference<XMultiServiceFactory> sm = getProcessServiceFactory(); 606 607 ConfigurationHelper::readDirectKey( 608 sm, 609 CFG_LOGGING, CFG_OOOIMPROVEMENT, CFG_LOGPATH, 610 ConfigurationHelper::E_READONLY 611 ) >>= result; 612 613 Reference<XStringSubstitution> path_sub( 614 sm->createInstance(CSSU_PATHSUB), 615 UNO_QUERY); 616 if(path_sub.is()) 617 result = path_sub->substituteVariables(result, sal_False); 618 return result; 619 } 620 621 TimeValue UiEventsLogger_Impl::getIdleTimeoutFromCfg() 622 { 623 sal_Int32 timeoutminutes = 360; 624 Reference<XMultiServiceFactory> sm = getProcessServiceFactory(); 625 626 ConfigurationHelper::readDirectKey( 627 sm, 628 CFG_LOGGING, CFG_OOOIMPROVEMENT, CFG_IDLETIMEOUT, 629 ConfigurationHelper::E_READONLY 630 ) >>= timeoutminutes; 631 TimeValue result; 632 result.Seconds = static_cast<sal_uInt32>(timeoutminutes)*60; 633 result.Nanosec = 0; 634 return result; 635 } 636 637 bool UiEventsLogger_Impl::getEnabledFromCfg() 638 { 639 sal_Bool result = false; 640 Reference<XMultiServiceFactory> sm = getProcessServiceFactory(); 641 ConfigurationHelper::readDirectKey( 642 sm, 643 CFG_LOGGING, CFG_OOOIMPROVEMENT, CFG_ENABLED, 644 ::comphelper::ConfigurationHelper::E_READONLY 645 ) >>= result; 646 return result; 647 } 648 649 bool UiEventsLogger_Impl::getEnabledFromCoreController() 650 { 651 Reference<XMultiServiceFactory> sm = getProcessServiceFactory(); 652 Reference<XCoreController> core_c( 653 sm->createInstance(OUString::createFromAscii("com.sun.star.oooimprovement.CoreController")), 654 UNO_QUERY); 655 if(!core_c.is()) return false; 656 return core_c->enablingUiEventsLoggerAllowed(1); 657 } 658 659 UiEventsLogger_Impl::ptr UiEventsLogger_Impl::instance = UiEventsLogger_Impl::ptr(); 660 UiEventsLogger_Impl::ptr UiEventsLogger_Impl::getInstance() 661 { 662 if(instance == NULL) 663 instance = UiEventsLogger_Impl::ptr(new UiEventsLogger_Impl()); 664 return instance; 665 } 666 667 Mutex * UiEventsLogger_Impl::singleton_mutex = NULL; 668 void UiEventsLogger_Impl::prepareMutex() 669 { 670 if(singleton_mutex == NULL) 671 { 672 Guard<Mutex> global_guard(Mutex::getGlobalMutex()); 673 if(singleton_mutex == NULL) 674 singleton_mutex = new Mutex(); 675 } 676 } 677 678 sal_Int32 UiEventsLogger_Impl::findIdx(const Sequence<PropertyValue>& args, const OUString& key) 679 { 680 for(sal_Int32 i=0; i<args.getLength(); i++) 681 if(args[i].Name == key) 682 return i; 683 return -1; 684 } 685 686 void UiEventsLogger_Impl::disposing() 687 { 688 m_Active = false; 689 m_Logger.clear() ; 690 m_LogHandler.clear(); 691 m_Formatter.clear(); 692 } 693 } 694