1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_extensions.hxx" 26 27 #include "log_module.hxx" 28 #include "methodguard.hxx" 29 #include "loghandler.hxx" 30 31 /** === begin UNO includes === **/ 32 #include <com/sun/star/logging/XConsoleHandler.hpp> 33 #include <com/sun/star/lang/XServiceInfo.hpp> 34 #include <com/sun/star/logging/LogLevel.hpp> 35 #include <com/sun/star/lang/XInitialization.hpp> 36 #include <com/sun/star/ucb/AlreadyInitializedException.hpp> 37 #include <com/sun/star/lang/IllegalArgumentException.hpp> 38 #include <com/sun/star/beans/NamedValue.hpp> 39 /** === end UNO includes === **/ 40 41 #include <tools/diagnose_ex.h> 42 43 #include <comphelper/componentcontext.hxx> 44 45 #include <cppuhelper/compbase3.hxx> 46 #include <cppuhelper/basemutex.hxx> 47 48 #include <rtl/strbuf.hxx> 49 #include <osl/process.h> 50 #include <osl/socket.hxx> 51 #include <osl/time.h> 52 53 #include <stdio.h> 54 55 //........................................................................ 56 namespace logging 57 { 58 //........................................................................ 59 60 /** === begin UNO using === **/ 61 using ::com::sun::star::logging::XLogHandler; 62 using ::com::sun::star::lang::XServiceInfo; 63 using ::com::sun::star::uno::Reference; 64 using ::com::sun::star::uno::XComponentContext; 65 using ::com::sun::star::uno::RuntimeException; 66 using ::com::sun::star::logging::XLogFormatter; 67 using ::com::sun::star::uno::Sequence; 68 using ::com::sun::star::logging::LogRecord; 69 using ::com::sun::star::uno::UNO_QUERY_THROW; 70 using ::com::sun::star::uno::Exception; 71 using ::com::sun::star::uno::Any; 72 using ::com::sun::star::uno::XInterface; 73 using ::com::sun::star::lang::XInitialization; 74 using ::com::sun::star::ucb::AlreadyInitializedException; 75 using ::com::sun::star::lang::IllegalArgumentException; 76 using ::com::sun::star::beans::NamedValue; 77 /** === end UNO using === **/ 78 namespace LogLevel = ::com::sun::star::logging::LogLevel; 79 80 //==================================================================== 81 //= SyslogHandler - declaration 82 //==================================================================== 83 //-------------------------------------------------------------------- 84 typedef ::cppu::WeakComponentImplHelper3 < XLogHandler 85 , XServiceInfo 86 , XInitialization 87 > SyslogHandler_Base; 88 class SyslogHandler :public ::cppu::BaseMutex 89 ,public SyslogHandler_Base 90 { 91 private: 92 ::comphelper::ComponentContext m_aContext; 93 LogHandlerHelper m_aHandlerHelper; 94 ::osl::SocketAddr m_aSocketAddress; 95 ::osl::DatagramSocket m_aSocket; 96 97 protected: 98 SyslogHandler( const Reference< XComponentContext >& _rxContext ); 99 virtual ~SyslogHandler(); 100 101 // XLogHandler 102 virtual ::rtl::OUString SAL_CALL getEncoding() throw (RuntimeException); 103 virtual void SAL_CALL setEncoding( const ::rtl::OUString& _encoding ) throw (RuntimeException); 104 virtual Reference< XLogFormatter > SAL_CALL getFormatter() throw (RuntimeException); 105 virtual void SAL_CALL setFormatter( const Reference< XLogFormatter >& _formatter ) throw (RuntimeException); 106 virtual ::sal_Int32 SAL_CALL getLevel() throw (RuntimeException); 107 virtual void SAL_CALL setLevel( ::sal_Int32 _level ) throw (RuntimeException); 108 virtual void SAL_CALL flush( ) throw (RuntimeException); 109 virtual ::sal_Bool SAL_CALL publish( const LogRecord& Record ) throw (RuntimeException); 110 111 // XInitialization 112 virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); 113 114 // XServiceInfo 115 virtual ::rtl::OUString SAL_CALL getImplementationName() throw(RuntimeException); 116 virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException); 117 virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(RuntimeException); 118 119 // OComponentHelper 120 virtual void SAL_CALL disposing(); 121 122 public: 123 // XServiceInfo - static version 124 static ::rtl::OUString SAL_CALL getImplementationName_static(); 125 static Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static(); 126 static Reference< XInterface > Create( const Reference< XComponentContext >& _rxContext ); 127 128 public: 129 typedef ComponentMethodGuard< SyslogHandler > MethodGuard; 130 void enterMethod( MethodGuard::Access ); 131 void leaveMethod( MethodGuard::Access ); 132 }; 133 134 //==================================================================== 135 //= SyslogHandler - implementation 136 //==================================================================== 137 //-------------------------------------------------------------------- SyslogHandler(const Reference<XComponentContext> & _rxContext)138 SyslogHandler::SyslogHandler( const Reference< XComponentContext >& _rxContext ) 139 :SyslogHandler_Base( m_aMutex ) 140 ,m_aContext( _rxContext ) 141 ,m_aHandlerHelper( _rxContext, m_aMutex, rBHelper ) 142 ,m_aSocketAddress() 143 ,m_aSocket() 144 { 145 } 146 147 //-------------------------------------------------------------------- ~SyslogHandler()148 SyslogHandler::~SyslogHandler() 149 { 150 if ( !rBHelper.bDisposed ) 151 { 152 acquire(); 153 dispose(); 154 } 155 } 156 157 //-------------------------------------------------------------------- disposing()158 void SAL_CALL SyslogHandler::disposing() 159 { 160 m_aHandlerHelper.setFormatter( NULL ); 161 } 162 163 //-------------------------------------------------------------------- enterMethod(MethodGuard::Access)164 void SyslogHandler::enterMethod( MethodGuard::Access ) 165 { 166 m_aHandlerHelper.enterMethod(); 167 } 168 169 //-------------------------------------------------------------------- leaveMethod(MethodGuard::Access)170 void SyslogHandler::leaveMethod( MethodGuard::Access ) 171 { 172 m_aMutex.release(); 173 } 174 175 //-------------------------------------------------------------------- getEncoding()176 ::rtl::OUString SAL_CALL SyslogHandler::getEncoding() throw (RuntimeException) 177 { 178 MethodGuard aGuard( *this ); 179 ::rtl::OUString sEncoding; 180 OSL_VERIFY( m_aHandlerHelper.getEncoding( sEncoding ) ); 181 return sEncoding; 182 } 183 184 //-------------------------------------------------------------------- setEncoding(const::rtl::OUString & _rEncoding)185 void SAL_CALL SyslogHandler::setEncoding( const ::rtl::OUString& _rEncoding ) throw (RuntimeException) 186 { 187 MethodGuard aGuard( *this ); 188 OSL_VERIFY( m_aHandlerHelper.setEncoding( _rEncoding ) ); 189 } 190 191 //-------------------------------------------------------------------- getFormatter()192 Reference< XLogFormatter > SAL_CALL SyslogHandler::getFormatter() throw (RuntimeException) 193 { 194 MethodGuard aGuard( *this ); 195 return m_aHandlerHelper.getFormatter(); 196 } 197 198 //-------------------------------------------------------------------- setFormatter(const Reference<XLogFormatter> & _rxFormatter)199 void SAL_CALL SyslogHandler::setFormatter( const Reference< XLogFormatter >& _rxFormatter ) throw (RuntimeException) 200 { 201 MethodGuard aGuard( *this ); 202 m_aHandlerHelper.setFormatter( _rxFormatter ); 203 } 204 205 //-------------------------------------------------------------------- getLevel()206 ::sal_Int32 SAL_CALL SyslogHandler::getLevel() throw (RuntimeException) 207 { 208 MethodGuard aGuard( *this ); 209 return m_aHandlerHelper.getLevel(); 210 } 211 212 //-------------------------------------------------------------------- setLevel(::sal_Int32 _nLevel)213 void SAL_CALL SyslogHandler::setLevel( ::sal_Int32 _nLevel ) throw (RuntimeException) 214 { 215 MethodGuard aGuard( *this ); 216 m_aHandlerHelper.setLevel( _nLevel ); 217 } 218 219 //-------------------------------------------------------------------- flush()220 void SAL_CALL SyslogHandler::flush( ) throw (RuntimeException) 221 { 222 MethodGuard aGuard( *this ); 223 fflush( stdout ); 224 fflush( stderr ); 225 } 226 227 //-------------------------------------------------------------------- publish(const LogRecord & _rRecord)228 ::sal_Bool SAL_CALL SyslogHandler::publish( const LogRecord& _rRecord ) throw (RuntimeException) 229 { 230 MethodGuard aGuard( *this ); 231 232 ::rtl::OString sEntry; 233 if ( !m_aHandlerHelper.formatForPublishing( _rRecord, sEntry ) ) 234 return sal_False; 235 236 ::rtl::OStringBuffer buffer; 237 // PRI 238 const sal_Int32 facility = 1; // USER 239 sal_Int32 severity; 240 switch ( _rRecord.Level ) 241 { 242 case LogLevel::SEVERE: 243 severity = 3; // error 244 break; 245 case LogLevel::WARNING: 246 severity = 4; // warning 247 break; 248 case LogLevel::INFO: 249 case LogLevel::CONFIG: 250 severity = 5; // notice 251 break; 252 default: 253 severity = 7; // debug 254 } 255 buffer.append( '<' ); 256 buffer.append( ( facility * 8 ) + severity ); 257 buffer.append( '>' ); 258 259 // VERSION 260 buffer.append( '1' ); 261 buffer.append( ' ' ); 262 263 // TIMESTAMP 264 char timestampBuffer[256]; 265 snprintf( timestampBuffer, sizeof( timestampBuffer ), 266 "%04i-%02i-%02iT%02i:%02i:%02i.%02iZ", 267 (int)_rRecord.LogTime.Year, (int)_rRecord.LogTime.Month, (int)_rRecord.LogTime.Day, 268 (int)_rRecord.LogTime.Hours, (int)_rRecord.LogTime.Minutes, (int)_rRecord.LogTime.Seconds, 269 (int)_rRecord.LogTime.HundredthSeconds ); 270 buffer.append( timestampBuffer ); 271 buffer.append( ' ' ); 272 273 // HOSTNAME 274 ::rtl::OUString hostname = ::osl::SocketAddr::getLocalHostname( 0 ); 275 if ( !hostname.isEmpty() ) 276 buffer.append( ::rtl::OUStringToOString( hostname, RTL_TEXTENCODING_UTF8 ) ); 277 else 278 buffer.append( '-' ); 279 buffer.append( ' ' ); 280 281 // APP-NAME 282 buffer.append( "soffice" ); 283 buffer.append( ' ' ); 284 285 // PROC-ID 286 oslProcessInfo pInfo; 287 pInfo.Size = sizeof(oslProcessInfo); 288 oslProcessError prerr = osl_getProcessInfo( NULL, osl_Process_IDENTIFIER, &pInfo ); 289 if ( prerr == osl_Process_E_None ) 290 buffer.append( (sal_Int64) pInfo.Ident ); 291 else 292 buffer.append( '-' ); 293 buffer.append( ' ' ); 294 295 // MESSAGE-ID 296 buffer.append( '-' ); 297 buffer.append( ' ' ); 298 299 // STRUCTURED DATA 300 buffer.append( '-' ); 301 buffer.append( ' ' ); 302 303 // MESSAGE 304 buffer.append( sEntry ); 305 306 sal_Int32 sockRes = m_aSocket.sendTo( m_aSocketAddress, buffer.getStr(), buffer.getLength() ); 307 308 return sockRes == osl_Socket_MsgNormal; 309 } 310 311 //-------------------------------------------------------------------- initialize(const Sequence<Any> & _rArguments)312 void SAL_CALL SyslogHandler::initialize( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException) 313 { 314 ::osl::MutexGuard aGuard( m_aMutex ); 315 316 if ( m_aHandlerHelper.getIsInitialized() ) 317 throw AlreadyInitializedException(); 318 319 if ( _rArguments.getLength() != 1 ) 320 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); 321 322 Sequence< NamedValue > aSettings; 323 if ( !( _rArguments[0] >>= aSettings ) ) 324 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); 325 326 // createWithSettings( [in] sequence< ::com::sun::star::beans::NamedValue > Settings ) 327 ::comphelper::NamedValueCollection aTypedSettings( aSettings ); 328 m_aHandlerHelper.initFromSettings( aTypedSettings ); 329 330 ::rtl::OUString host; 331 if ( !aTypedSettings.get_ensureType( "Host", host ) ) 332 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); 333 sal_Int32 port; 334 if ( !aTypedSettings.get_ensureType( "Port", port ) ) 335 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); 336 ::osl::SocketAddr address( host, port ); 337 if ( address.is() ) 338 m_aSocketAddress = address; 339 else 340 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); 341 342 m_aHandlerHelper.setIsInitialized(); 343 } 344 345 //-------------------------------------------------------------------- getImplementationName()346 ::rtl::OUString SAL_CALL SyslogHandler::getImplementationName() throw(RuntimeException) 347 { 348 return getImplementationName_static(); 349 } 350 351 //-------------------------------------------------------------------- supportsService(const::rtl::OUString & _rServiceName)352 ::sal_Bool SAL_CALL SyslogHandler::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException) 353 { 354 const Sequence< ::rtl::OUString > aServiceNames( getSupportedServiceNames() ); 355 for ( const ::rtl::OUString* pServiceNames = aServiceNames.getConstArray(); 356 pServiceNames != aServiceNames.getConstArray() + aServiceNames.getLength(); 357 ++pServiceNames 358 ) 359 if ( _rServiceName == *pServiceNames ) 360 return sal_True; 361 return sal_False; 362 } 363 364 //-------------------------------------------------------------------- getSupportedServiceNames()365 Sequence< ::rtl::OUString > SAL_CALL SyslogHandler::getSupportedServiceNames() throw(RuntimeException) 366 { 367 return getSupportedServiceNames_static(); 368 } 369 370 //-------------------------------------------------------------------- getImplementationName_static()371 ::rtl::OUString SAL_CALL SyslogHandler::getImplementationName_static() 372 { 373 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.SyslogHandler" ) ); 374 } 375 376 //-------------------------------------------------------------------- getSupportedServiceNames_static()377 Sequence< ::rtl::OUString > SAL_CALL SyslogHandler::getSupportedServiceNames_static() 378 { 379 Sequence< ::rtl::OUString > aServiceNames(1); 380 aServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.logging.SyslogHandler" ) ); 381 return aServiceNames; 382 } 383 384 //-------------------------------------------------------------------- Create(const Reference<XComponentContext> & _rxContext)385 Reference< XInterface > SyslogHandler::Create( const Reference< XComponentContext >& _rxContext ) 386 { 387 return *( new SyslogHandler( _rxContext ) ); 388 } 389 390 //-------------------------------------------------------------------- createRegistryInfo_SyslogHandler()391 void createRegistryInfo_SyslogHandler() 392 { 393 static OAutoRegistration< SyslogHandler > aAutoRegistration; 394 } 395 396 //........................................................................ 397 } // namespace logging 398 //........................................................................ 399