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