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_comphelper.hxx"
26 #include <comphelper/officeresourcebundle.hxx>
27 
28 /** === begin UNO includes === **/
29 #include <com/sun/star/resource/XResourceBundle.hpp>
30 #include <com/sun/star/resource/XResourceBundleLoader.hpp>
31 #include <com/sun/star/lang/NullPointerException.hpp>
32 /** === end UNO includes === **/
33 #include <osl/mutex.hxx>
34 #include <osl/diagnose.h>
35 #include <rtl/ustrbuf.hxx>
36 
37 //........................................................................
38 namespace comphelper
39 {
40 //........................................................................
41 
42     /** === begin UNO using === **/
43     using ::com::sun::star::uno::Reference;
44     using com::sun::star::resource::XResourceBundle;
45     using com::sun::star::resource::XResourceBundleLoader;
46     using com::sun::star::resource::MissingResourceException;
47     using ::com::sun::star::uno::XComponentContext;
48     using ::com::sun::star::lang::NullPointerException;
49     using ::com::sun::star::uno::UNO_QUERY;
50     using ::com::sun::star::uno::Exception;
51     using ::com::sun::star::uno::Any;
52     /** === end UNO using === **/
53 
54     //====================================================================
55 	//= ResourceBundle_Impl
56 	//====================================================================
57     class ResourceBundle_Impl
58     {
59     private:
60         Reference< XComponentContext >  m_xContext;
61         ::rtl::OUString                 m_sBaseName;
62         Reference< XResourceBundle >    m_xBundle;
63         bool                            m_bAttemptedCreate;
64         mutable ::osl::Mutex            m_aMutex;
65 
66     public:
ResourceBundle_Impl(const Reference<XComponentContext> & _context,const::rtl::OUString & _baseName)67         ResourceBundle_Impl( const Reference< XComponentContext >& _context, const ::rtl::OUString& _baseName )
68             :m_xContext( _context )
69             ,m_sBaseName( _baseName )
70             ,m_bAttemptedCreate( false )
71         {
72         }
73 
74     public:
75         /** loads the string with the given resource id from the resource bundle
76             @param  _resourceId
77                 the id of the string to load
78             @return
79                 the requested resource string. If no string with the given id exists in the resource bundle,
80                 an empty string is returned. In a non-product version, an OSL_ENSURE will notify you of this
81                 then.
82         */
83         ::rtl::OUString loadString( sal_Int32 _resourceId ) const;
84 
85         /** determines whether the resource bundle has a string with the given id
86             @param  _resourceId
87                 the id of the string whose existence is to be checked
88             @return
89                 <TRUE/> if and only if a string with the given ID exists in the resource
90                 bundle.
91         */
92         bool            hasString( sal_Int32 _resourceId ) const;
93 
94     private:
95         /** loads the bundle represented by the instance
96 
97             The method is safe against multiple calls: If a previos call succeeded or failed, the
98             previous result will be returned, without any other processing.
99 
100             @precond
101                 Our mutex is locked.
102         */
103         bool    impl_loadBundle_nothrow();
104 
105         /** returns the resource bundle key for a string with a given resource id
106         */
107         static ::rtl::OUString
108                 impl_getStringResourceKey( sal_Int32 _resourceId );
109     };
110 
111 	//--------------------------------------------------------------------
impl_getStringResourceKey(sal_Int32 _resourceId)112     ::rtl::OUString ResourceBundle_Impl::impl_getStringResourceKey( sal_Int32 _resourceId )
113     {
114         ::rtl::OUStringBuffer key;
115         key.appendAscii( "string:" );
116         key.append( _resourceId );
117         return key.makeStringAndClear();
118     }
119 
120 	//--------------------------------------------------------------------
loadString(sal_Int32 _resourceId) const121     ::rtl::OUString ResourceBundle_Impl::loadString( sal_Int32 _resourceId ) const
122     {
123         ::osl::MutexGuard aGuard( m_aMutex );
124 
125         ::rtl::OUString sString;
126 
127         if ( const_cast< ResourceBundle_Impl* >( this )->impl_loadBundle_nothrow() )
128         {
129             try
130             {
131                 OSL_VERIFY( m_xBundle->getByName( impl_getStringResourceKey( _resourceId ) ) >>= sString );
132             }
133             catch( const Exception& )
134             {
135                 OSL_ENSURE( false, "ResourceBundle_Impl::loadString: caught an exception!" );
136             }
137         }
138         return sString;
139     }
140 
141 	//--------------------------------------------------------------------
hasString(sal_Int32 _resourceId) const142     bool ResourceBundle_Impl::hasString( sal_Int32 _resourceId ) const
143     {
144         ::osl::MutexGuard aGuard( m_aMutex );
145 
146         bool has = false;
147 
148         if ( const_cast< ResourceBundle_Impl* >( this )->impl_loadBundle_nothrow() )
149         {
150             try
151             {
152                 has = m_xBundle->hasByName( impl_getStringResourceKey( _resourceId ) );
153             }
154             catch( const Exception& )
155             {
156                 OSL_ENSURE( false, "ResourceBundle_Impl::hasString: caught an exception!" );
157             }
158         }
159         return has;
160     }
161 
162 	//--------------------------------------------------------------------
impl_loadBundle_nothrow()163     bool ResourceBundle_Impl::impl_loadBundle_nothrow()
164     {
165         if ( m_bAttemptedCreate )
166             return m_xBundle.is();
167 
168         m_bAttemptedCreate = true;
169 
170         Reference< XResourceBundleLoader > xLoader;
171         try
172         {
173             Any aValue( m_xContext->getValueByName(
174                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
175                     "/singletons/com.sun.star.resource.OfficeResourceLoader" ) ) ) );
176             OSL_VERIFY( aValue >>= xLoader );
177         }
178         catch( const Exception& )
179         {
180             OSL_ENSURE( false, "ResourceBundle_Impl::impl_loadBundle_nopthrow: could not create the resource loader!" );
181         }
182 
183         if ( !xLoader.is() )
184             return false;
185 
186         try
187         {
188             m_xBundle = xLoader->loadBundle_Default( m_sBaseName );
189         }
190         catch( const MissingResourceException& )
191         {
192             OSL_ENSURE( false, "ResourceBundle_Impl::impl_loadBundle_nopthrow: missing the given resource bundle!" );
193         }
194 
195         return m_xBundle.is();
196     }
197 
198 	//====================================================================
199 	//= OfficeResourceBundle
200 	//====================================================================
201 	//--------------------------------------------------------------------
OfficeResourceBundle(const Reference<XComponentContext> & _context,const::rtl::OUString & _bundleBaseName)202     OfficeResourceBundle::OfficeResourceBundle( const Reference< XComponentContext >& _context, const ::rtl::OUString& _bundleBaseName )
203         :m_pImpl( new ResourceBundle_Impl( _context, _bundleBaseName ) )
204     {
205         if ( !_context.is() )
206             throw NullPointerException();
207     }
208 
209 	//--------------------------------------------------------------------
OfficeResourceBundle(const Reference<XComponentContext> & _context,const sal_Char * _bundleBaseAsciiName)210     OfficeResourceBundle::OfficeResourceBundle( const Reference< XComponentContext >& _context, const sal_Char* _bundleBaseAsciiName )
211         :m_pImpl( new ResourceBundle_Impl( _context, ::rtl::OUString::createFromAscii( _bundleBaseAsciiName ) ) )
212     {
213         if ( !_context.is() )
214             throw NullPointerException();
215     }
216 
217 	//--------------------------------------------------------------------
~OfficeResourceBundle()218     OfficeResourceBundle::~OfficeResourceBundle()
219     {
220     }
221 
222 	//--------------------------------------------------------------------
loadString(sal_Int32 _resourceId) const223     ::rtl::OUString OfficeResourceBundle::loadString( sal_Int32 _resourceId ) const
224     {
225         return m_pImpl->loadString( _resourceId );
226     }
227 
228 	//--------------------------------------------------------------------
hasString(sal_Int32 _resourceId) const229     bool OfficeResourceBundle::hasString( sal_Int32 _resourceId ) const
230     {
231         return m_pImpl->hasString( _resourceId );
232     }
233 
234 //........................................................................
235 } // namespace comphelper
236 //........................................................................
237