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_extensions.hxx" 30 31 #ifndef EXTENSIONS_SOURCE_RESOURCE_OOORESOURCELOADER_CXX 32 #define EXTENSIONS_SOURCE_RESOURCE_OOORESOURCELOADER_CXX 33 #include "res_services.hxx" 34 35 /** === begin UNO includes === **/ 36 #include <com/sun/star/resource/XResourceBundleLoader.hpp> 37 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 38 #include <com/sun/star/uno/XComponentContext.hpp> 39 /** === end UNO includes === **/ 40 #include <vcl/svapp.hxx> 41 #include <tools/simplerm.hxx> 42 #include <tools/rcid.h> 43 #include <cppuhelper/implbase1.hxx> 44 #include <cppuhelper/weakref.hxx> 45 46 #include <boost/shared_ptr.hpp> 47 #include <map> 48 49 //........................................................................ 50 namespace res 51 { 52 //........................................................................ 53 54 /** === begin UNO using === **/ 55 using ::com::sun::star::uno::Reference; 56 using ::com::sun::star::resource::XResourceBundleLoader; 57 using ::com::sun::star::resource::XResourceBundle; 58 using ::com::sun::star::resource::MissingResourceException; 59 using ::com::sun::star::uno::XComponentContext; 60 using ::com::sun::star::uno::Sequence; 61 using ::com::sun::star::uno::XInterface; 62 using ::com::sun::star::uno::RuntimeException; 63 using ::com::sun::star::lang::Locale; 64 using ::com::sun::star::uno::Any; 65 using ::com::sun::star::container::NoSuchElementException; 66 using ::com::sun::star::lang::WrappedTargetException; 67 using ::com::sun::star::uno::Type; 68 using ::com::sun::star::uno::WeakReference; 69 /** === end UNO using === **/ 70 71 //==================================================================== 72 //= helper 73 //==================================================================== 74 typedef ::std::pair< ::rtl::OUString, Locale > ResourceBundleDescriptor; 75 76 struct ResourceBundleDescriptorLess : public ::std::binary_function< ResourceBundleDescriptor, ResourceBundleDescriptor, bool > 77 { 78 bool operator()( const ResourceBundleDescriptor& _lhs, const ResourceBundleDescriptor& _rhs ) const 79 { 80 if ( _lhs.first < _rhs.first ) 81 return true; 82 if ( _lhs.second.Language < _rhs.second.Language ) 83 return true; 84 if ( _lhs.second.Country < _rhs.second.Country ) 85 return true; 86 if ( _lhs.second.Variant < _rhs.second.Variant ) 87 return true; 88 return false; 89 } 90 }; 91 92 //==================================================================== 93 //= OpenOfficeResourceLoader 94 //==================================================================== 95 typedef ::cppu::WeakImplHelper1 < XResourceBundleLoader 96 > OpenOfficeResourceLoader_Base; 97 class OpenOfficeResourceLoader : public OpenOfficeResourceLoader_Base 98 { 99 private: 100 typedef ::std::map< ResourceBundleDescriptor, WeakReference< XResourceBundle >, ResourceBundleDescriptorLess > 101 ResourceBundleCache; 102 103 private: 104 Reference< XComponentContext > m_xContext; 105 ::osl::Mutex m_aMutex; 106 ResourceBundleCache m_aBundleCache; 107 108 protected: 109 OpenOfficeResourceLoader( const Reference< XComponentContext >& _rxContext ); 110 111 public: 112 static Sequence< ::rtl::OUString > getSupportedServiceNames_static(); 113 static ::rtl::OUString getImplementationName_static(); 114 static ::rtl::OUString getSingletonName_static(); 115 static Reference< XInterface > Create( const Reference< XComponentContext >& _rxContext ); 116 117 // XResourceBundleLoader 118 virtual Reference< XResourceBundle > SAL_CALL loadBundle_Default( const ::rtl::OUString& aBaseName ) throw (MissingResourceException, RuntimeException); 119 virtual Reference< XResourceBundle > SAL_CALL loadBundle( const ::rtl::OUString& abaseName, const Locale& aLocale ) throw (MissingResourceException, RuntimeException); 120 121 private: 122 OpenOfficeResourceLoader(); // never implemented 123 OpenOfficeResourceLoader( const OpenOfficeResourceLoader& ); // never implemented 124 OpenOfficeResourceLoader& operator=( const OpenOfficeResourceLoader& ); // never implemented 125 }; 126 127 //==================================================================== 128 //= IResourceType 129 //==================================================================== 130 /** encapsulates access to a fixed resource type 131 */ 132 class IResourceType 133 { 134 public: 135 /** returns the RESOURCE_TYPE associated with this instance 136 */ 137 virtual RESOURCE_TYPE getResourceType() const = 0; 138 139 /** reads a single resource from the given resource manager 140 @param _resourceManager 141 the resource manager to read from 142 @param _resourceId 143 the id of the resource to read 144 @return 145 the required resource 146 @precond 147 the caler checked via <code>_resourceManager.IsAvailable( getResourceType(), _resourceId )</code> 148 that the required resource really exists 149 */ 150 virtual Any getResource( SimpleResMgr& _resourceManager, sal_Int32 _resourceId ) const = 0; 151 152 virtual ~IResourceType() { }; 153 }; 154 155 //==================================================================== 156 //= StringResourceAccess 157 //==================================================================== 158 class StringResourceAccess : public IResourceType 159 { 160 public: 161 StringResourceAccess(); 162 163 // IResourceType 164 virtual RESOURCE_TYPE getResourceType() const; 165 virtual Any getResource( SimpleResMgr& _resourceManager, sal_Int32 _resourceId ) const; 166 }; 167 168 //-------------------------------------------------------------------- 169 StringResourceAccess::StringResourceAccess() 170 { 171 } 172 173 //-------------------------------------------------------------------- 174 RESOURCE_TYPE StringResourceAccess::getResourceType() const 175 { 176 return RSC_STRING; 177 } 178 179 //-------------------------------------------------------------------- 180 Any StringResourceAccess::getResource( SimpleResMgr& _resourceManager, sal_Int32 _resourceId ) const 181 { 182 OSL_PRECOND( _resourceManager.IsAvailable( getResourceType(), _resourceId ), "StringResourceAccess::getResource: precondition not met!" ); 183 Any aResource; 184 aResource <<= ::rtl::OUString( _resourceManager.ReadString( _resourceId ) ); 185 return aResource; 186 } 187 188 //==================================================================== 189 //= OpenOfficeResourceBundle 190 //==================================================================== 191 typedef ::cppu::WeakImplHelper1 < XResourceBundle 192 > OpenOfficeResourceBundle_Base; 193 class OpenOfficeResourceBundle : public OpenOfficeResourceBundle_Base 194 { 195 private: 196 typedef ::boost::shared_ptr< IResourceType > ResourceTypePtr; 197 typedef ::std::map< ::rtl::OUString, ResourceTypePtr > ResourceTypes; 198 199 ::osl::Mutex m_aMutex; 200 Reference< XResourceBundle > m_xParent; 201 Locale m_aLocale; 202 SimpleResMgr* m_pResourceManager; 203 ResourceTypes m_aResourceTypes; 204 205 public: 206 OpenOfficeResourceBundle( 207 const Reference< XComponentContext >& _rxContext, 208 const ::rtl::OUString& _rBaseName, 209 const Locale& _rLocale 210 ); 211 212 protected: 213 ~OpenOfficeResourceBundle(); 214 215 public: 216 // XResourceBundle 217 virtual ::com::sun::star::uno::Reference< ::com::sun::star::resource::XResourceBundle > SAL_CALL getParent() throw (::com::sun::star::uno::RuntimeException); 218 virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::resource::XResourceBundle >& _parent ) throw (::com::sun::star::uno::RuntimeException); 219 virtual ::com::sun::star::lang::Locale SAL_CALL getLocale( ) throw (::com::sun::star::uno::RuntimeException); 220 virtual ::com::sun::star::uno::Any SAL_CALL getDirectElement( const ::rtl::OUString& key ) throw (::com::sun::star::uno::RuntimeException); 221 222 // XNameAccess (base of XResourceBundle) 223 virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); 224 virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (::com::sun::star::uno::RuntimeException); 225 virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException); 226 227 // XElementAccess (base of XNameAccess) 228 virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) throw (::com::sun::star::uno::RuntimeException); 229 virtual ::sal_Bool SAL_CALL hasElements( ) throw (::com::sun::star::uno::RuntimeException); 230 231 private: 232 /** retrievs the element with the given key, without asking our parent bundle 233 @param _key 234 the key of the element to retrieve 235 @param _out_Element 236 will contained the retrieved element upon successful return. If the method is unsuccessful, the 237 value will not be touched. 238 @return 239 <TRUE/> if and only if the element could be retrieved 240 @precond 241 our mutex is locked 242 */ 243 bool impl_getDirectElement_nothrow( const ::rtl::OUString& _key, Any& _out_Element ) const; 244 245 /** retrieves the resource type and id from a given resource key, which assembles those two 246 @param _key 247 the resource key as got via a public API call 248 @param _out_resourceType 249 the resource type, if successful 250 @param _out_resourceId 251 the resource id, if successful 252 @return 253 <TRUE/> if and only if the given key specifies a known resource type, and contains a valid 254 resource id 255 */ 256 bool impl_getResourceTypeAndId_nothrow( const ::rtl::OUString& _key, ResourceTypePtr& _out_resourceType, sal_Int32& _out_resourceId ) const; 257 }; 258 259 //==================================================================== 260 //= OpenOfficeResourceLoader 261 //==================================================================== 262 //-------------------------------------------------------------------- 263 OpenOfficeResourceLoader::OpenOfficeResourceLoader( const Reference< XComponentContext >& _rxContext ) 264 :m_xContext( _rxContext ) 265 { 266 } 267 268 //-------------------------------------------------------------------- 269 Sequence< ::rtl::OUString > OpenOfficeResourceLoader::getSupportedServiceNames_static() 270 { 271 Sequence< ::rtl::OUString > aServices( 1 ); 272 aServices[ 0 ] = getSingletonName_static(); 273 return aServices; 274 } 275 276 //-------------------------------------------------------------------- 277 ::rtl::OUString OpenOfficeResourceLoader::getImplementationName_static() 278 { 279 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.resource.OpenOfficeResourceLoader" ) ); 280 } 281 282 //-------------------------------------------------------------------- 283 ::rtl::OUString OpenOfficeResourceLoader::getSingletonName_static() 284 { 285 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.resource.OfficeResourceLoader" ) ); 286 } 287 288 //-------------------------------------------------------------------- 289 Reference< XInterface > OpenOfficeResourceLoader::Create( const Reference< XComponentContext >& _rxContext ) 290 { 291 return *( new OpenOfficeResourceLoader( _rxContext ) ); 292 } 293 294 //-------------------------------------------------------------------- 295 Reference< XResourceBundle > SAL_CALL OpenOfficeResourceLoader::loadBundle_Default( const ::rtl::OUString& _baseName ) throw (MissingResourceException, RuntimeException) 296 { 297 return loadBundle( _baseName, Application::GetSettings().GetUILocale() ); 298 } 299 300 //-------------------------------------------------------------------- 301 Reference< XResourceBundle > SAL_CALL OpenOfficeResourceLoader::loadBundle( const ::rtl::OUString& _baseName, const Locale& _locale ) throw (MissingResourceException, RuntimeException) 302 { 303 ::osl::MutexGuard aGuard( m_aMutex ); 304 305 Reference< XResourceBundle > xBundle; 306 307 ResourceBundleDescriptor resourceDescriptor( _baseName, _locale ); 308 ResourceBundleCache::iterator cachePos = m_aBundleCache.find( resourceDescriptor ); 309 if ( cachePos != m_aBundleCache.end() ) 310 xBundle = cachePos->second; 311 312 if ( !xBundle.is() ) 313 { // not in the cache, or already died 314 xBundle = new OpenOfficeResourceBundle( m_xContext, _baseName, _locale ); 315 m_aBundleCache.insert( ResourceBundleCache::value_type( resourceDescriptor, xBundle ) ); 316 } 317 318 return xBundle; 319 } 320 321 //-------------------------------------------------------------------- 322 ComponentInfo getComponentInfo_OpenOfficeResourceLoader() 323 { 324 ComponentInfo aInfo; 325 aInfo.aSupportedServices = OpenOfficeResourceLoader::getSupportedServiceNames_static(); 326 aInfo.sImplementationName = OpenOfficeResourceLoader::getImplementationName_static(); 327 aInfo.sSingletonName = OpenOfficeResourceLoader::getSingletonName_static(); 328 aInfo.pFactory = &OpenOfficeResourceLoader::Create; 329 return aInfo; 330 } 331 332 //==================================================================== 333 //= OpenOfficeResourceBundle 334 //==================================================================== 335 //-------------------------------------------------------------------- 336 OpenOfficeResourceBundle::OpenOfficeResourceBundle( const Reference< XComponentContext >& /*_rxContext*/, const ::rtl::OUString& _rBaseName, const Locale& _rLocale ) 337 :m_aLocale( _rLocale ) 338 ,m_pResourceManager( NULL ) 339 { 340 ::rtl::OUString sBaseName( _rBaseName ); 341 m_pResourceManager = new SimpleResMgr( sBaseName, m_aLocale ); 342 343 if ( !m_pResourceManager->IsValid() ) 344 { 345 delete m_pResourceManager, m_pResourceManager = NULL; 346 throw MissingResourceException(); 347 } 348 349 // supported resource types so far: strings 350 m_aResourceTypes[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "string" ) ) ] = 351 ResourceTypePtr( new StringResourceAccess ); 352 } 353 354 //-------------------------------------------------------------------- 355 OpenOfficeResourceBundle::~OpenOfficeResourceBundle() 356 { 357 delete m_pResourceManager; 358 } 359 360 //-------------------------------------------------------------------- 361 Reference< XResourceBundle > SAL_CALL OpenOfficeResourceBundle::getParent() throw (RuntimeException) 362 { 363 ::osl::MutexGuard aGuard( m_aMutex ); 364 return m_xParent; 365 } 366 367 //-------------------------------------------------------------------- 368 void SAL_CALL OpenOfficeResourceBundle::setParent( const Reference< XResourceBundle >& _parent ) throw (RuntimeException) 369 { 370 ::osl::MutexGuard aGuard( m_aMutex ); 371 m_xParent = _parent; 372 } 373 374 //-------------------------------------------------------------------- 375 Locale SAL_CALL OpenOfficeResourceBundle::getLocale( ) throw (RuntimeException) 376 { 377 ::osl::MutexGuard aGuard( m_aMutex ); 378 return m_aLocale; 379 } 380 381 //-------------------------------------------------------------------- 382 bool OpenOfficeResourceBundle::impl_getResourceTypeAndId_nothrow( const ::rtl::OUString& _key, ResourceTypePtr& _out_resourceType, sal_Int32& _out_resourceId ) const 383 { 384 sal_Int32 typeSeparatorPos = _key.indexOf( ':' ); 385 if ( typeSeparatorPos == -1 ) 386 // invalid key 387 return false; 388 389 ::rtl::OUString resourceType = _key.copy( 0, typeSeparatorPos ); 390 391 ResourceTypes::const_iterator typePos = m_aResourceTypes.find( resourceType ); 392 if ( typePos == m_aResourceTypes.end() ) 393 // don't know this resource type 394 return false; 395 396 _out_resourceType = typePos->second; 397 _out_resourceId = _key.copy( typeSeparatorPos + 1 ).toInt32(); 398 return true; 399 } 400 401 //-------------------------------------------------------------------- 402 bool OpenOfficeResourceBundle::impl_getDirectElement_nothrow( const ::rtl::OUString& _key, Any& _out_Element ) const 403 { 404 ResourceTypePtr resourceType; 405 sal_Int32 resourceId( 0 ); 406 if ( !impl_getResourceTypeAndId_nothrow( _key, resourceType, resourceId ) ) 407 return false; 408 409 if ( !m_pResourceManager->IsAvailable( resourceType->getResourceType(), resourceId ) ) 410 // no such resource with the given type/id 411 return false; 412 413 _out_Element = resourceType->getResource( *m_pResourceManager, resourceId ); 414 return _out_Element.hasValue(); 415 } 416 417 //-------------------------------------------------------------------- 418 Any SAL_CALL OpenOfficeResourceBundle::getDirectElement( const ::rtl::OUString& _key ) throw (RuntimeException) 419 { 420 ::osl::MutexGuard aGuard( m_aMutex ); 421 422 Any aElement; 423 impl_getDirectElement_nothrow( _key, aElement ); 424 return aElement; 425 } 426 427 //-------------------------------------------------------------------- 428 Any SAL_CALL OpenOfficeResourceBundle::getByName( const ::rtl::OUString& _key ) throw (NoSuchElementException, WrappedTargetException, RuntimeException) 429 { 430 ::osl::MutexGuard aGuard( m_aMutex ); 431 432 Any aElement; 433 if ( !impl_getDirectElement_nothrow( _key, aElement ) ) 434 { 435 if ( m_xParent.is() ) 436 aElement = m_xParent->getByName( _key ); 437 } 438 439 if ( !aElement.hasValue() ) 440 throw NoSuchElementException( ::rtl::OUString(), *this ); 441 442 return aElement; 443 } 444 445 //-------------------------------------------------------------------- 446 Sequence< ::rtl::OUString > SAL_CALL OpenOfficeResourceBundle::getElementNames( ) throw (RuntimeException) 447 { 448 ::osl::MutexGuard aGuard( m_aMutex ); 449 OSL_ENSURE( false, "OpenOfficeResourceBundle::getElementNames: not implemented!" ); 450 // the (Simple)ResManager does not provide an API to enumerate the resources 451 return Sequence< ::rtl::OUString >( ); 452 } 453 454 //-------------------------------------------------------------------- 455 ::sal_Bool SAL_CALL OpenOfficeResourceBundle::hasByName( const ::rtl::OUString& _key ) throw (RuntimeException) 456 { 457 ::osl::MutexGuard aGuard( m_aMutex ); 458 459 ResourceTypePtr resourceType; 460 sal_Int32 resourceId( 0 ); 461 if ( !impl_getResourceTypeAndId_nothrow( _key, resourceType, resourceId ) ) 462 return sal_False; 463 464 if ( !m_pResourceManager->IsAvailable( resourceType->getResourceType(), resourceId ) ) 465 return sal_False; 466 467 return sal_True; 468 } 469 470 //-------------------------------------------------------------------- 471 Type SAL_CALL OpenOfficeResourceBundle::getElementType( ) throw (RuntimeException) 472 { 473 return ::cppu::UnoType< Any >::get(); 474 } 475 476 //-------------------------------------------------------------------- 477 ::sal_Bool SAL_CALL OpenOfficeResourceBundle::hasElements( ) throw (RuntimeException) 478 { 479 ::osl::MutexGuard aGuard( m_aMutex ); 480 OSL_ENSURE( false, "OpenOfficeResourceBundle::hasElements: not implemented!" ); 481 // the (Simple)ResManager does not provide an API to enumerate the resources 482 return ::sal_Bool( ); 483 } 484 485 //........................................................................ 486 } // namespace res 487 //........................................................................ 488 489 #endif // EXTENSIONS_SOURCE_RESOURCE_OOORESOURCELOADER_CXX 490