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