1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_xmlhelp.hxx" 30 31 /************************************************************************** 32 TODO 33 ************************************************************************** 34 35 *************************************************************************/ 36 37 #include <stdio.h> 38 #include <osl/file.hxx> 39 #ifndef _VOS_DIAGNOSE_HXX_ 40 #include <vos/diagnose.hxx> 41 #endif 42 #include <ucbhelper/contentidentifier.hxx> 43 #include <com/sun/star/frame/XConfigManager.hpp> 44 #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBBUTE_HPP_ 45 #include <com/sun/star/beans/PropertyAttribute.hpp> 46 #endif 47 #include <com/sun/star/beans/PropertyValue.hpp> 48 #include <com/sun/star/container/XContainer.hpp> 49 #include <com/sun/star/container/XNameAccess.hpp> 50 #include <com/sun/star/container/XNameReplace.hpp> 51 #include <com/sun/star/uno/XComponentContext.hpp> 52 #include <com/sun/star/beans/XPropertySet.hpp> 53 #include <rtl/bootstrap.hxx> 54 55 #include "databases.hxx" 56 #include "provider.hxx" 57 #include "content.hxx" 58 #include "databases.hxx" 59 60 using namespace com::sun::star; 61 using namespace chelp; 62 63 //========================================================================= 64 //========================================================================= 65 // 66 // ContentProvider Implementation. 67 // 68 //========================================================================= 69 //========================================================================= 70 71 ContentProvider::ContentProvider( 72 const uno::Reference< lang::XMultiServiceFactory >& rSMgr ) 73 : ::ucbhelper::ContentProviderImplHelper( rSMgr ), 74 isInitialized( false ), 75 m_aScheme( rtl::OUString::createFromAscii( MYUCP_URL_SCHEME ) ), 76 m_pDatabases( 0 ) 77 { 78 } 79 80 //========================================================================= 81 // virtual 82 ContentProvider::~ContentProvider() 83 { 84 delete m_pDatabases; 85 } 86 87 //========================================================================= 88 // 89 // XInterface methods. 90 // 91 //========================================================================= 92 93 XINTERFACE_IMPL_6( ContentProvider, 94 lang::XTypeProvider, 95 lang::XServiceInfo, 96 ucb::XContentProvider, 97 lang::XComponent, 98 lang::XEventListener, /* base of XContainerListener */ 99 container::XContainerListener); 100 101 //========================================================================= 102 // 103 // XTypeProvider methods. 104 // 105 //========================================================================= 106 107 XTYPEPROVIDER_IMPL_5( ContentProvider, 108 lang::XTypeProvider, 109 lang::XServiceInfo, 110 ucb::XContentProvider, 111 lang::XComponent, 112 container::XContainerListener); 113 114 //========================================================================= 115 // 116 // XServiceInfo methods. 117 // 118 //========================================================================= 119 120 rtl::OUString SAL_CALL ContentProvider::getImplementationName() 121 throw( uno::RuntimeException ) 122 { 123 return getImplementationName_Static(); 124 } 125 126 rtl::OUString ContentProvider::getImplementationName_Static() 127 { 128 return rtl::OUString::createFromAscii("CHelpContentProvider" ); 129 } 130 131 sal_Bool SAL_CALL 132 ContentProvider::supportsService(const rtl::OUString& ServiceName ) 133 throw( uno::RuntimeException ) 134 { 135 uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames(); 136 const rtl::OUString* pArray = aSNL.getArray(); 137 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) 138 { 139 if( pArray[ i ] == ServiceName ) 140 return sal_True; 141 } 142 143 return sal_False; 144 } 145 146 uno::Sequence< rtl::OUString > SAL_CALL 147 ContentProvider::getSupportedServiceNames() 148 throw( uno::RuntimeException ) 149 { 150 return getSupportedServiceNames_Static(); 151 } 152 153 static uno::Reference< uno::XInterface > SAL_CALL 154 ContentProvider_CreateInstance( 155 const uno::Reference< lang::XMultiServiceFactory> & rSMgr ) 156 throw( uno::Exception ) 157 { 158 lang::XServiceInfo * pX = static_cast< lang::XServiceInfo * >( 159 new ContentProvider( rSMgr ) ); 160 return uno::Reference< uno::XInterface >::query( pX ); 161 } 162 163 uno::Sequence< rtl::OUString > 164 ContentProvider::getSupportedServiceNames_Static() 165 { 166 uno::Sequence< rtl::OUString > aSNS( 2 ); 167 aSNS.getArray()[ 0 ] = 168 rtl::OUString::createFromAscii( 169 MYUCP_CONTENT_PROVIDER_SERVICE_NAME1 ); 170 aSNS.getArray()[ 1 ] = 171 rtl::OUString::createFromAscii( 172 MYUCP_CONTENT_PROVIDER_SERVICE_NAME2 ); 173 174 return aSNS; 175 } 176 177 //========================================================================= 178 // 179 // Service factory implementation. 180 // 181 //========================================================================= 182 183 ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider ); 184 185 //========================================================================= 186 // 187 // XContentProvider methods. 188 // 189 //========================================================================= 190 191 // virtual 192 uno::Reference< ucb::XContent > SAL_CALL 193 ContentProvider::queryContent( 194 const uno::Reference< ucb::XContentIdentifier >& xCanonicId ) 195 throw( ucb::IllegalIdentifierException, uno::RuntimeException ) 196 { 197 if ( !xCanonicId->getContentProviderScheme() 198 .equalsIgnoreAsciiCase( m_aScheme ) ) 199 { // Wrong URL-scheme 200 throw ucb::IllegalIdentifierException(); 201 } 202 203 { 204 osl::MutexGuard aGuard( m_aMutex ); 205 if( !isInitialized ) 206 init(); 207 } 208 209 if( !m_pDatabases ) 210 throw uno::RuntimeException(); 211 212 rtl::OUString aOUString( m_pDatabases->getInstallPathAsURL() ); 213 rtl::OString aOString( aOUString.getStr(), 214 aOUString.getLength(), 215 RTL_TEXTENCODING_UTF8 ); 216 217 // Check, if a content with given id already exists... 218 uno::Reference< ucb::XContent > xContent 219 = queryExistingContent( xCanonicId ).get(); 220 if ( xContent.is() ) 221 return xContent; 222 223 xContent = new Content( m_xSMgr, this, xCanonicId, m_pDatabases ); 224 225 // register new content 226 registerNewContent( xContent ); 227 228 // Further checks 229 230 if ( !xContent->getIdentifier().is() ) 231 throw ucb::IllegalIdentifierException(); 232 233 return xContent; 234 } 235 236 void SAL_CALL 237 ContentProvider::dispose() 238 throw ( uno::RuntimeException) 239 { 240 if(m_xContainer.is()) 241 { 242 m_xContainer->removeContainerListener(this); 243 m_xContainer.clear(); 244 } 245 } 246 247 void SAL_CALL 248 ContentProvider::elementReplaced(const container::ContainerEvent& Event) 249 throw (uno::RuntimeException) 250 { 251 if(!m_pDatabases) 252 return; 253 254 rtl::OUString accessor; 255 Event.Accessor >>= accessor; 256 if(accessor.compareToAscii("HelpStyleSheet")) 257 return; 258 259 rtl::OUString replacedElement,element; 260 Event.ReplacedElement >>= replacedElement; 261 Event.Element >>= element; 262 263 if(replacedElement == element) 264 return; 265 266 m_pDatabases->changeCSS(element); 267 } 268 269 void ContentProvider::init() 270 { 271 osl::MutexGuard aGuard( m_aMutex ); 272 273 isInitialized = true; 274 uno::Reference< lang::XMultiServiceFactory > sProvider( 275 getConfiguration() ); 276 uno::Reference< container::XHierarchicalNameAccess > xHierAccess( 277 getHierAccess( sProvider, 278 "org.openoffice.Office.Common" ) ); 279 280 rtl::OUString instPath( getKey( xHierAccess,"Path/Current/Help" ) ); 281 if( ! instPath.getLength() ) 282 // try to determine path from default 283 instPath = rtl::OUString::createFromAscii( "$(instpath)/help" ); 284 // replace anything like $(instpath); 285 subst( instPath ); 286 287 rtl::OUString stylesheet( getKey( xHierAccess,"Help/HelpStyleSheet" ) ); 288 try 289 { 290 // now adding as configuration change listener for the stylesheet 291 uno::Reference< container::XNameAccess> xAccess( 292 xHierAccess, uno::UNO_QUERY ); 293 if( xAccess.is() ) 294 { 295 uno::Any aAny = 296 xAccess->getByName( rtl::OUString::createFromAscii( "Help" ) ); 297 aAny >>= m_xContainer; 298 if( m_xContainer.is() ) 299 m_xContainer->addContainerListener( this ); 300 } 301 } 302 catch( uno::Exception const & ) 303 { 304 } 305 306 /** 307 * now determing 308 * productname, 309 * productversion, 310 */ 311 312 xHierAccess = getHierAccess( sProvider, "org.openoffice.Setup" ); 313 rtl::OUString productname( 314 getKey( xHierAccess,"Product/ooName" ) ); 315 316 rtl::OUString setupversion( 317 getKey( xHierAccess,"Product/ooSetupVersion" ) ); 318 rtl::OUString setupextension; 319 320 try 321 { 322 uno::Reference< lang::XMultiServiceFactory > xConfigProvider( 323 m_xSMgr ->createInstance(::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider")), uno::UNO_QUERY_THROW); 324 325 uno::Sequence < uno::Any > lParams(1); 326 beans::PropertyValue aParam ; 327 aParam.Name = ::rtl::OUString::createFromAscii("nodepath"); 328 aParam.Value <<= ::rtl::OUString::createFromAscii("/org.openoffice.Setup/Product"); 329 lParams[0] = uno::makeAny(aParam); 330 331 // open it 332 uno::Reference< uno::XInterface > xCFG( xConfigProvider->createInstanceWithArguments( 333 ::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess"), 334 lParams) ); 335 336 uno::Reference< container::XNameAccess > xDirectAccess(xCFG, uno::UNO_QUERY); 337 uno::Any aRet = xDirectAccess->getByName(::rtl::OUString::createFromAscii("ooSetupExtension")); 338 339 aRet >>= setupextension; 340 } 341 catch ( uno::Exception& ) 342 { 343 } 344 345 rtl::OUString productversion( 346 setupversion + 347 rtl::OUString::createFromAscii( " " ) + 348 setupextension ); 349 350 uno::Sequence< rtl::OUString > aImagesZipPaths( 2 ); 351 xHierAccess = getHierAccess( sProvider, "org.openoffice.Office.Common" ); 352 353 rtl::OUString aPath( getKey( xHierAccess, "Path/Current/UserConfig" ) ); 354 subst( aPath ); 355 aImagesZipPaths[ 0 ] = aPath; 356 357 aPath = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/share/config")); 358 rtl::Bootstrap::expandMacros(aPath); 359 aImagesZipPaths[ 1 ] = aPath; 360 361 uno::Reference< uno::XComponentContext > xContext; 362 uno::Reference< beans::XPropertySet > xProps( m_xSMgr, uno::UNO_QUERY ); 363 OSL_ASSERT( xProps.is() ); 364 if (xProps.is()) 365 { 366 xProps->getPropertyValue( 367 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xContext; 368 OSL_ASSERT( xContext.is() ); 369 } 370 371 sal_Bool showBasic = getBooleanKey(xHierAccess,"Help/ShowBasic"); 372 m_pDatabases = new Databases( showBasic, 373 instPath, 374 aImagesZipPaths, 375 productname, 376 productversion, 377 stylesheet, 378 xContext ); 379 } 380 381 uno::Reference< lang::XMultiServiceFactory > 382 ContentProvider::getConfiguration() const 383 { 384 uno::Reference< lang::XMultiServiceFactory > sProvider; 385 if( m_xSMgr.is() ) 386 { 387 try 388 { 389 rtl::OUString sProviderService = 390 rtl::OUString::createFromAscii( 391 "com.sun.star.configuration.ConfigurationProvider" ); 392 sProvider = 393 uno::Reference< lang::XMultiServiceFactory >( 394 m_xSMgr->createInstance( sProviderService ), 395 uno::UNO_QUERY ); 396 } 397 catch( const uno::Exception& ) 398 { 399 OSL_ENSURE( sProvider.is(), "cant instantiate configuration" ); 400 } 401 } 402 403 return sProvider; 404 } 405 406 uno::Reference< container::XHierarchicalNameAccess > 407 ContentProvider::getHierAccess( 408 const uno::Reference< lang::XMultiServiceFactory >& sProvider, 409 const char* file ) const 410 { 411 uno::Reference< container::XHierarchicalNameAccess > xHierAccess; 412 413 if( sProvider.is() ) 414 { 415 uno::Sequence< uno::Any > seq( 1 ); 416 rtl::OUString sReaderService( 417 rtl::OUString::createFromAscii( 418 "com.sun.star.configuration.ConfigurationAccess" ) ); 419 420 seq[ 0 ] <<= rtl::OUString::createFromAscii( file ); 421 422 try 423 { 424 xHierAccess = 425 uno::Reference< container::XHierarchicalNameAccess >( 426 sProvider->createInstanceWithArguments( 427 sReaderService, seq ), 428 uno::UNO_QUERY ); 429 } 430 catch( const uno::Exception& ) 431 { 432 } 433 } 434 return xHierAccess; 435 } 436 437 438 439 rtl::OUString 440 ContentProvider::getKey( 441 const uno::Reference< container::XHierarchicalNameAccess >& xHierAccess, 442 const char* key ) const 443 { 444 rtl::OUString instPath; 445 if( xHierAccess.is() ) 446 { 447 uno::Any aAny; 448 try 449 { 450 aAny = 451 xHierAccess->getByHierarchicalName( 452 rtl::OUString::createFromAscii( key ) ); 453 } 454 catch( const container::NoSuchElementException& ) 455 { 456 } 457 aAny >>= instPath; 458 } 459 return instPath; 460 } 461 462 sal_Bool 463 ContentProvider::getBooleanKey( 464 const uno::Reference< container::XHierarchicalNameAccess >& xHierAccess, 465 const char* key ) const 466 { 467 sal_Bool ret = sal_False; 468 if( xHierAccess.is() ) 469 { 470 uno::Any aAny; 471 try 472 { 473 aAny = 474 xHierAccess->getByHierarchicalName( 475 rtl::OUString::createFromAscii( key ) ); 476 } 477 catch( const container::NoSuchElementException& ) 478 { 479 } 480 aAny >>= ret; 481 } 482 return ret; 483 } 484 485 void ContentProvider::subst( rtl::OUString& instpath ) const 486 { 487 uno::Reference< frame::XConfigManager > xCfgMgr; 488 if( m_xSMgr.is() ) 489 { 490 try 491 { 492 xCfgMgr = 493 uno::Reference< frame::XConfigManager >( 494 m_xSMgr->createInstance( 495 rtl::OUString::createFromAscii( 496 "com.sun.star.config.SpecialConfigManager" ) ), 497 uno::UNO_QUERY ); 498 } 499 catch( const uno::Exception&) 500 { 501 OSL_ENSURE( xCfgMgr.is(), 502 "cant instantiate the special config manager " ); 503 } 504 } 505 506 OSL_ENSURE( xCfgMgr.is(), "specialconfigmanager not found\n" ); 507 508 if( xCfgMgr.is() ) 509 instpath = xCfgMgr->substituteVariables( instpath ); 510 } 511