Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <oooresourceloader.hxx>
22 : #include <vcl/svapp.hxx>
23 : #include <tools/simplerm.hxx>
24 : #include <tools/rcid.h>
25 : #include <cppuhelper/implbase1.hxx>
26 : #include <cppuhelper/weakref.hxx>
27 :
28 : #include <boost/shared_ptr.hpp>
29 : #include <map>
30 :
31 : using namespace ::com::sun::star::uno;
32 : using namespace ::com::sun::star::resource;
33 : using namespace ::com::sun::star::container;
34 : using namespace ::com::sun::star::lang;
35 :
36 :
37 : namespace extensions { namespace resource
38 : {
39 : /** encapsulates access to a fixed resource type
40 : */
41 0 : class IResourceType
42 : {
43 : public:
44 : /** returns the RESOURCE_TYPE associated with this instance
45 : */
46 : virtual RESOURCE_TYPE getResourceType() const = 0;
47 :
48 : /** reads a single resource from the given resource manager
49 : @param _resourceManager
50 : the resource manager to read from
51 : @param _resourceId
52 : the id of the resource to read
53 : @return
54 : the required resource
55 : @precond
56 : the caler checked via <code>_resourceManager.IsAvailable( getResourceType(), _resourceId )</code>
57 : that the required resource really exists
58 : */
59 : virtual Any getResource( SimpleResMgr& _resourceManager, sal_Int32 _resourceId ) const = 0;
60 :
61 0 : virtual ~IResourceType() { };
62 : };
63 :
64 0 : class StringResourceAccess : public IResourceType
65 : {
66 : public:
67 : StringResourceAccess();
68 :
69 : // IResourceType
70 : virtual RESOURCE_TYPE getResourceType() const;
71 : virtual Any getResource( SimpleResMgr& _resourceManager, sal_Int32 _resourceId ) const;
72 : };
73 :
74 0 : StringResourceAccess::StringResourceAccess()
75 : {
76 0 : }
77 :
78 0 : RESOURCE_TYPE StringResourceAccess::getResourceType() const
79 : {
80 0 : return RSC_STRING;
81 : }
82 :
83 0 : Any StringResourceAccess::getResource( SimpleResMgr& _resourceManager, sal_Int32 _resourceId ) const
84 : {
85 : OSL_PRECOND( _resourceManager.IsAvailable( getResourceType(), _resourceId ), "StringResourceAccess::getResource: precondition not met!" );
86 0 : Any aResource;
87 0 : aResource <<= ::rtl::OUString( _resourceManager.ReadString( _resourceId ) );
88 0 : return aResource;
89 : }
90 :
91 : typedef ::cppu::WeakImplHelper1 < XResourceBundle
92 : > OpenOfficeResourceBundle_Base;
93 : class OpenOfficeResourceBundle : public OpenOfficeResourceBundle_Base
94 : {
95 : private:
96 : typedef ::boost::shared_ptr< IResourceType > ResourceTypePtr;
97 : typedef ::std::map< ::rtl::OUString, ResourceTypePtr > ResourceTypes;
98 :
99 : ::osl::Mutex m_aMutex;
100 : Reference< XResourceBundle > m_xParent;
101 : Locale m_aLocale;
102 : SimpleResMgr* m_pResourceManager;
103 : ResourceTypes m_aResourceTypes;
104 :
105 : public:
106 : OpenOfficeResourceBundle(
107 : const Reference< XComponentContext >& _rxContext,
108 : const ::rtl::OUString& _rBaseName,
109 : const Locale& _rLocale
110 : );
111 :
112 : protected:
113 : ~OpenOfficeResourceBundle();
114 :
115 : public:
116 : // XResourceBundle
117 : virtual ::com::sun::star::uno::Reference< ::com::sun::star::resource::XResourceBundle > SAL_CALL getParent() throw (::com::sun::star::uno::RuntimeException);
118 : virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::resource::XResourceBundle >& _parent ) throw (::com::sun::star::uno::RuntimeException);
119 : virtual ::com::sun::star::lang::Locale SAL_CALL getLocale( ) throw (::com::sun::star::uno::RuntimeException);
120 : virtual ::com::sun::star::uno::Any SAL_CALL getDirectElement( const ::rtl::OUString& key ) throw (::com::sun::star::uno::RuntimeException);
121 :
122 : // XNameAccess (base of XResourceBundle)
123 : 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);
124 : virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (::com::sun::star::uno::RuntimeException);
125 : virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException);
126 :
127 : // XElementAccess (base of XNameAccess)
128 : virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) throw (::com::sun::star::uno::RuntimeException);
129 : virtual ::sal_Bool SAL_CALL hasElements( ) throw (::com::sun::star::uno::RuntimeException);
130 :
131 : private:
132 : /** retrievs the element with the given key, without asking our parent bundle
133 : @param _key
134 : the key of the element to retrieve
135 : @param _out_Element
136 : will contained the retrieved element upon successful return. If the method is unsuccessful, the
137 : value will not be touched.
138 : @return
139 : <TRUE/> if and only if the element could be retrieved
140 : @precond
141 : our mutex is locked
142 : */
143 : bool impl_getDirectElement_nothrow( const ::rtl::OUString& _key, Any& _out_Element ) const;
144 :
145 : /** retrieves the resource type and id from a given resource key, which assembles those two
146 : @param _key
147 : the resource key as got via a public API call
148 : @param _out_resourceType
149 : the resource type, if successful
150 : @param _out_resourceId
151 : the resource id, if successful
152 : @return
153 : <TRUE/> if and only if the given key specifies a known resource type, and contains a valid
154 : resource id
155 : */
156 : bool impl_getResourceTypeAndId_nothrow( const ::rtl::OUString& _key, ResourceTypePtr& _out_resourceType, sal_Int32& _out_resourceId ) const;
157 : };
158 :
159 0 : OpenOfficeResourceLoader::OpenOfficeResourceLoader( Reference< XComponentContext > const& _rxContext )
160 0 : :m_xContext( _rxContext )
161 : {
162 0 : }
163 :
164 : //--------------------------------------------------------------------
165 0 : Reference< XResourceBundle > SAL_CALL OpenOfficeResourceLoader::loadBundle_Default( const ::rtl::OUString& _baseName ) throw (MissingResourceException, RuntimeException)
166 : {
167 0 : return loadBundle( _baseName, Application::GetSettings().GetUILanguageTag().getLocale() );
168 : }
169 :
170 : //--------------------------------------------------------------------
171 0 : Reference< XResourceBundle > SAL_CALL OpenOfficeResourceLoader::loadBundle( const ::rtl::OUString& _baseName, const Locale& _locale ) throw (MissingResourceException, RuntimeException)
172 : {
173 0 : ::osl::MutexGuard aGuard( m_aMutex );
174 :
175 0 : Reference< XResourceBundle > xBundle;
176 :
177 0 : ResourceBundleDescriptor resourceDescriptor( _baseName, _locale );
178 0 : ResourceBundleCache::iterator cachePos = m_aBundleCache.find( resourceDescriptor );
179 0 : if ( cachePos != m_aBundleCache.end() )
180 0 : xBundle = cachePos->second;
181 :
182 0 : if ( !xBundle.is() )
183 : { // not in the cache, or already died
184 0 : xBundle = new OpenOfficeResourceBundle( m_xContext, _baseName, _locale );
185 0 : m_aBundleCache.insert( ResourceBundleCache::value_type( resourceDescriptor, xBundle ) );
186 : }
187 :
188 0 : return xBundle;
189 : }
190 :
191 0 : OpenOfficeResourceBundle::OpenOfficeResourceBundle( const Reference< XComponentContext >& /*_rxContext*/, const ::rtl::OUString& _rBaseName, const Locale& _rLocale )
192 : :m_aLocale( _rLocale )
193 0 : ,m_pResourceManager( NULL )
194 : {
195 0 : ::rtl::OUString sBaseName( _rBaseName );
196 0 : m_pResourceManager = new SimpleResMgr( rtl::OUStringToOString( sBaseName, RTL_TEXTENCODING_UTF8 ).getStr(), m_aLocale );
197 :
198 0 : if ( !m_pResourceManager->IsValid() )
199 : {
200 0 : delete m_pResourceManager, m_pResourceManager = NULL;
201 0 : throw MissingResourceException();
202 : }
203 :
204 : // supported resource types so far: strings
205 0 : m_aResourceTypes[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "string" ) ) ] =
206 0 : ResourceTypePtr( new StringResourceAccess );
207 0 : }
208 :
209 0 : OpenOfficeResourceBundle::~OpenOfficeResourceBundle()
210 : {
211 0 : delete m_pResourceManager;
212 0 : }
213 :
214 0 : Reference< XResourceBundle > SAL_CALL OpenOfficeResourceBundle::getParent() throw (RuntimeException)
215 : {
216 0 : ::osl::MutexGuard aGuard( m_aMutex );
217 0 : return m_xParent;
218 : }
219 :
220 0 : void SAL_CALL OpenOfficeResourceBundle::setParent( const Reference< XResourceBundle >& _parent ) throw (RuntimeException)
221 : {
222 0 : ::osl::MutexGuard aGuard( m_aMutex );
223 0 : m_xParent = _parent;
224 0 : }
225 :
226 0 : Locale SAL_CALL OpenOfficeResourceBundle::getLocale( ) throw (RuntimeException)
227 : {
228 0 : ::osl::MutexGuard aGuard( m_aMutex );
229 0 : return m_aLocale;
230 : }
231 :
232 0 : bool OpenOfficeResourceBundle::impl_getResourceTypeAndId_nothrow( const ::rtl::OUString& _key, ResourceTypePtr& _out_resourceType, sal_Int32& _out_resourceId ) const
233 : {
234 0 : sal_Int32 typeSeparatorPos = _key.indexOf( ':' );
235 0 : if ( typeSeparatorPos == -1 )
236 : // invalid key
237 0 : return false;
238 :
239 0 : ::rtl::OUString resourceType = _key.copy( 0, typeSeparatorPos );
240 :
241 0 : ResourceTypes::const_iterator typePos = m_aResourceTypes.find( resourceType );
242 0 : if ( typePos == m_aResourceTypes.end() )
243 : // don't know this resource type
244 0 : return false;
245 :
246 0 : _out_resourceType = typePos->second;
247 0 : _out_resourceId = _key.copy( typeSeparatorPos + 1 ).toInt32();
248 0 : return true;
249 : }
250 :
251 0 : bool OpenOfficeResourceBundle::impl_getDirectElement_nothrow( const ::rtl::OUString& _key, Any& _out_Element ) const
252 : {
253 0 : ResourceTypePtr resourceType;
254 0 : sal_Int32 resourceId( 0 );
255 0 : if ( !impl_getResourceTypeAndId_nothrow( _key, resourceType, resourceId ) )
256 0 : return false;
257 :
258 0 : if ( !m_pResourceManager->IsAvailable( resourceType->getResourceType(), resourceId ) )
259 : // no such resource with the given type/id
260 0 : return false;
261 :
262 0 : _out_Element = resourceType->getResource( *m_pResourceManager, resourceId );
263 0 : return _out_Element.hasValue();
264 : }
265 :
266 0 : Any SAL_CALL OpenOfficeResourceBundle::getDirectElement( const ::rtl::OUString& _key ) throw (RuntimeException)
267 : {
268 0 : ::osl::MutexGuard aGuard( m_aMutex );
269 :
270 0 : Any aElement;
271 0 : impl_getDirectElement_nothrow( _key, aElement );
272 0 : return aElement;
273 : }
274 :
275 0 : Any SAL_CALL OpenOfficeResourceBundle::getByName( const ::rtl::OUString& _key ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
276 : {
277 0 : ::osl::MutexGuard aGuard( m_aMutex );
278 :
279 0 : Any aElement;
280 0 : if ( !impl_getDirectElement_nothrow( _key, aElement ) )
281 : {
282 0 : if ( m_xParent.is() )
283 0 : aElement = m_xParent->getByName( _key );
284 : }
285 :
286 0 : if ( !aElement.hasValue() )
287 0 : throw NoSuchElementException( ::rtl::OUString(), *this );
288 :
289 0 : return aElement;
290 : }
291 :
292 0 : Sequence< ::rtl::OUString > SAL_CALL OpenOfficeResourceBundle::getElementNames( ) throw (RuntimeException)
293 : {
294 0 : ::osl::MutexGuard aGuard( m_aMutex );
295 : OSL_FAIL( "OpenOfficeResourceBundle::getElementNames: not implemented!" );
296 : // the (Simple)ResManager does not provide an API to enumerate the resources
297 0 : return Sequence< ::rtl::OUString >( );
298 : }
299 :
300 0 : ::sal_Bool SAL_CALL OpenOfficeResourceBundle::hasByName( const ::rtl::OUString& _key ) throw (RuntimeException)
301 : {
302 0 : ::osl::MutexGuard aGuard( m_aMutex );
303 :
304 0 : ResourceTypePtr resourceType;
305 0 : sal_Int32 resourceId( 0 );
306 0 : if ( !impl_getResourceTypeAndId_nothrow( _key, resourceType, resourceId ) )
307 0 : return sal_False;
308 :
309 0 : if ( !m_pResourceManager->IsAvailable( resourceType->getResourceType(), resourceId ) )
310 0 : return sal_False;
311 :
312 0 : return sal_True;
313 : }
314 :
315 0 : Type SAL_CALL OpenOfficeResourceBundle::getElementType( ) throw (RuntimeException)
316 : {
317 0 : return ::cppu::UnoType< Any >::get();
318 : }
319 :
320 0 : ::sal_Bool SAL_CALL OpenOfficeResourceBundle::hasElements( ) throw (RuntimeException)
321 : {
322 0 : ::osl::MutexGuard aGuard( m_aMutex );
323 : OSL_FAIL( "OpenOfficeResourceBundle::hasElements: not implemented!" );
324 : // the (Simple)ResManager does not provide an API to enumerate the resources
325 0 : return ::sal_Bool( );
326 : }
327 :
328 : }}
329 :
330 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|