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