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