xref: /trunk/main/connectivity/source/commontools/sqlerror.cxx (revision d3e5b9da5ecd3a21afd95e21a5fd36807d0753aa)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_connectivity.hxx"
24 
25 #include "connectivity/sqlerror.hxx"
26 
27 /** === begin UNO includes === **/
28 #include <com/sun/star/sdbc/SQLException.hpp>
29 /** === end UNO includes === **/
30 
31 #include <comphelper/officeresourcebundle.hxx>
32 #include <cppuhelper/exc_hlp.hxx>
33 #include <rtl/ustrbuf.hxx>
34 
35 #include <string.h>
36 
37 namespace connectivity
38 {
39 
40     /** === begin UNO using === **/
41     using ::com::sun::star::uno::Reference;
42     using ::com::sun::star::uno::UNO_QUERY;
43     using ::com::sun::star::uno::UNO_QUERY_THROW;
44     using ::com::sun::star::uno::Exception;
45     using ::com::sun::star::uno::RuntimeException;
46     using ::com::sun::star::uno::Any;
47     using ::com::sun::star::uno::makeAny;
48     using ::com::sun::star::uno::XInterface;
49     using ::com::sun::star::sdbc::SQLException;
50     using ::com::sun::star::uno::Type;
51     /** === end UNO using === **/
52 
53     //using SQLError::ParamValue; // GCC (unxlngi6) does not like this
54     namespace
55     {
56         typedef SQLError::ParamValue ParamValue;
57     }
58 
59     //====================================================================
60     //= SQLError_Impl - declaration
61     //====================================================================
62     class SQLError_Impl
63     {
64     public:
65         SQLError_Impl( const ::comphelper::ComponentContext& _rContext );
66         ~SQLError_Impl();
67 
68         // versions of the public SQLError methods which are just delegated to this impl-class
69         static const ::rtl::OUString& getMessagePrefix();
70         ::rtl::OUString     getErrorMessage( const ErrorCondition _eCondition, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 );
71         ::rtl::OUString     getSQLState( const ErrorCondition _eCondition );
72         static ErrorCode    getErrorCode( const ErrorCondition _eCondition );
73         void                raiseException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 );
74         void                raiseException( const ErrorCondition _eCondition, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 );
75         void                raiseTypedException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, const Type& _rExceptionType, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 );
76         SQLException        getSQLException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 );
77 
78     private:
79         // returns the basic error message associated with the given error condition, without any parameter replacements
80         ::rtl::OUString
81                 impl_getErrorMessage( const ErrorCondition& _eCondition );
82 
83         // returns the SQLState associated with the given error condition
84         ::rtl::OUString
85                 impl_getSQLState( const ErrorCondition& _eCondition );
86 
87         // returns an SQLException describing the given error condition
88         SQLException
89                 impl_buildSQLException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext,
90                     const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 );
91 
92         // initializes our resource bundle
93         bool    impl_initResources();
94 
95     private:
96         ::osl::Mutex                                            m_aMutex;
97         ::comphelper::ComponentContext                          m_aContext;
98         ::std::auto_ptr< ::comphelper::OfficeResourceBundle >   m_pResources;
99         bool                                                    m_bAttemptedInit;
100     };
101 
102     //====================================================================
103     //= SQLError_Impl - implementation
104     //====================================================================
105     //--------------------------------------------------------------------
SQLError_Impl(const::comphelper::ComponentContext & _rContext)106     SQLError_Impl::SQLError_Impl( const ::comphelper::ComponentContext& _rContext )
107         :m_aContext( _rContext )
108         ,m_pResources( )
109         ,m_bAttemptedInit( false )
110     {
111     }
112 
113     //--------------------------------------------------------------------
~SQLError_Impl()114     SQLError_Impl::~SQLError_Impl()
115     {
116     }
117 
118     //--------------------------------------------------------------------
getMessagePrefix()119     const ::rtl::OUString& SQLError_Impl::getMessagePrefix()
120     {
121         static ::rtl::OUString s_sMessagePrefix( RTL_CONSTASCII_USTRINGPARAM( "[OOoBase]" ) );
122         return s_sMessagePrefix;
123     }
124 
125     //--------------------------------------------------------------------
126     namespace
127     {
128         //................................................................
129         /** substitutes a given placeholder in the given message with the given value
130         */
lcl_substitutePlaceholder(::rtl::OUString & _rMessage,const sal_Char * _pPlaceholder,ParamValue _rParamValue)131         void    lcl_substitutePlaceholder( ::rtl::OUString& _rMessage, const sal_Char* _pPlaceholder, ParamValue _rParamValue )
132         {
133             size_t nPlaceholderLen( strlen( _pPlaceholder ) );
134             sal_Int32 nIndex = _rMessage.indexOfAsciiL( _pPlaceholder, nPlaceholderLen );
135 
136             bool bHasPlaceholder = ( nIndex != -1 );
137             bool bWantsPlaceholder = _rParamValue.is();
138             OSL_ENSURE( bHasPlaceholder == bWantsPlaceholder, "lcl_substitutePlaceholder: placeholder where none is expected, or no placeholder where one is needed!" );
139 
140             if ( bHasPlaceholder && bWantsPlaceholder )
141                 _rMessage = _rMessage.replaceAt( nIndex, nPlaceholderLen, *_rParamValue );
142         }
143 
144         //................................................................
lcl_getResourceID(const ErrorCondition _eCondition,bool _bSQLState)145         sal_Int32   lcl_getResourceID( const ErrorCondition _eCondition, bool _bSQLState )
146         {
147             return  256
148                 +   2 * ::sal::static_int_cast< sal_Int32, ErrorCondition >( _eCondition )
149                 +   ( _bSQLState ? 1 : 0 );
150         }
151     }
152 
153     //--------------------------------------------------------------------
getErrorMessage(const ErrorCondition _eCondition,const ParamValue & _rParamValue1,const ParamValue & _rParamValue2,const ParamValue & _rParamValue3)154     ::rtl::OUString SQLError_Impl::getErrorMessage( const ErrorCondition _eCondition, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 )
155     {
156         ::rtl::OUString sErrorMessage( impl_getErrorMessage( _eCondition ) );
157 
158         lcl_substitutePlaceholder( sErrorMessage, "$1$", _rParamValue1 );
159         lcl_substitutePlaceholder( sErrorMessage, "$2$", _rParamValue2 );
160         lcl_substitutePlaceholder( sErrorMessage, "$3$", _rParamValue3 );
161 
162         return sErrorMessage;
163     }
164 
165     //--------------------------------------------------------------------
getSQLState(const ErrorCondition _eCondition)166     ::rtl::OUString SQLError_Impl::getSQLState( const ErrorCondition _eCondition )
167     {
168         return impl_getSQLState( _eCondition );
169     }
170 
171     //--------------------------------------------------------------------
getErrorCode(const ErrorCondition _eCondition)172     ErrorCode SQLError_Impl::getErrorCode( const ErrorCondition _eCondition )
173     {
174         return 0 - ::sal::static_int_cast< ErrorCode, ErrorCondition >( _eCondition );
175     }
176 
177     //--------------------------------------------------------------------
raiseException(const ErrorCondition _eCondition,const Reference<XInterface> & _rxContext,const ParamValue & _rParamValue1,const ParamValue & _rParamValue2,const ParamValue & _rParamValue3)178     void SQLError_Impl::raiseException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 )
179     {
180         raiseTypedException(
181             _eCondition,
182             _rxContext,
183             ::cppu::UnoType< SQLException >::get(),
184             _rParamValue1,
185             _rParamValue2,
186             _rParamValue3
187         );
188     }
189 
190     //--------------------------------------------------------------------
raiseException(const ErrorCondition _eCondition,const ParamValue & _rParamValue1,const ParamValue & _rParamValue2,const ParamValue & _rParamValue3)191     void SQLError_Impl::raiseException( const ErrorCondition _eCondition, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 )
192     {
193         raiseTypedException(
194             _eCondition,
195             NULL,
196             ::cppu::UnoType< SQLException >::get(),
197             _rParamValue1,
198             _rParamValue2,
199             _rParamValue3
200         );
201     }
202 
203     //--------------------------------------------------------------------
raiseTypedException(const ErrorCondition _eCondition,const Reference<XInterface> & _rxContext,const Type & _rExceptionType,const ParamValue & _rParamValue1,const ParamValue & _rParamValue2,const ParamValue & _rParamValue3)204     void SQLError_Impl::raiseTypedException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext,
205         const Type& _rExceptionType, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 )
206     {
207         if ( !::cppu::UnoType< SQLException >::get().isAssignableFrom( _rExceptionType ) )
208             throw ::std::bad_cast();
209 
210         // default-construct an exception of the desired type
211         Any aException( NULL, _rExceptionType );
212 
213         // fill it
214         SQLException* pException = static_cast< SQLException* >( aException.pData );
215         *pException = impl_buildSQLException( _eCondition, _rxContext, _rParamValue1, _rParamValue2, _rParamValue3 );
216 
217         // throw it
218         ::cppu::throwException( aException );
219     }
220 
221     //--------------------------------------------------------------------
getSQLException(const ErrorCondition _eCondition,const Reference<XInterface> & _rxContext,const ParamValue & _rParamValue1,const ParamValue & _rParamValue2,const ParamValue & _rParamValue3)222     SQLException SQLError_Impl::getSQLException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext,
223         const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 )
224     {
225         return impl_buildSQLException( _eCondition, _rxContext, _rParamValue1, _rParamValue2, _rParamValue3 );
226     }
227 
228     //--------------------------------------------------------------------
impl_buildSQLException(const ErrorCondition _eCondition,const Reference<XInterface> & _rxContext,const ParamValue & _rParamValue1,const ParamValue & _rParamValue2,const ParamValue & _rParamValue3)229     SQLException SQLError_Impl::impl_buildSQLException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext,
230         const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 )
231     {
232         return SQLException(
233             getErrorMessage( _eCondition, _rParamValue1, _rParamValue2, _rParamValue3 ),
234             _rxContext,
235             getSQLState( _eCondition ),
236             getErrorCode( _eCondition ),
237             Any()
238         );
239     }
240 
241     //--------------------------------------------------------------------
impl_getErrorMessage(const ErrorCondition & _eCondition)242     ::rtl::OUString SQLError_Impl::impl_getErrorMessage( const ErrorCondition& _eCondition )
243     {
244         ::rtl::OUStringBuffer aMessage;
245 
246         if ( impl_initResources() )
247         {
248             ::rtl::OUString sResMessage( m_pResources->loadString( lcl_getResourceID( _eCondition, false ) ) );
249             OSL_ENSURE( sResMessage.getLength(), "SQLError_Impl::impl_getErrorMessage: illegal error condition, or invalid resource!" );
250             aMessage.append( getMessagePrefix() ).appendAscii( " " ).append( sResMessage );
251         }
252 
253         return aMessage.makeStringAndClear();
254     }
255 
256     //--------------------------------------------------------------------
impl_getSQLState(const ErrorCondition & _eCondition)257     ::rtl::OUString SQLError_Impl::impl_getSQLState( const ErrorCondition& _eCondition )
258     {
259         ::rtl::OUString sState;
260 
261         if ( impl_initResources() )
262         {
263             sal_Int32 nResourceId( lcl_getResourceID( _eCondition, true ) );
264             if ( m_pResources->hasString( nResourceId ) )
265                 sState = m_pResources->loadString( nResourceId );
266         }
267 
268         if ( !sState.getLength() )
269             sState = ::rtl::OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "S1000" ) );
270 
271         return sState;
272     }
273 
274     //--------------------------------------------------------------------
impl_initResources()275     bool SQLError_Impl::impl_initResources()
276     {
277         if ( m_pResources.get() )
278             return true;
279         if ( m_bAttemptedInit )
280             return false;
281 
282         ::osl::MutexGuard aGuard( m_aMutex );
283         m_bAttemptedInit = true;
284 
285         m_pResources.reset( new ::comphelper::OfficeResourceBundle( m_aContext.getUNOContext(), "sdberr" ) );
286         return m_pResources.get() != NULL;
287     }
288 
289     //====================================================================
290     //= SQLError
291     //====================================================================
292     //--------------------------------------------------------------------
SQLError(const::comphelper::ComponentContext & _rContext)293     SQLError::SQLError( const ::comphelper::ComponentContext& _rContext )
294         :m_pImpl( new SQLError_Impl( _rContext ) )
295     {
296     }
297 
298     //--------------------------------------------------------------------
~SQLError()299     SQLError::~SQLError()
300     {
301     }
302 
303     //--------------------------------------------------------------------
getMessagePrefix()304     const ::rtl::OUString& SQLError::getMessagePrefix()
305     {
306         return SQLError_Impl::getMessagePrefix();
307     }
308 
309     //--------------------------------------------------------------------
getErrorMessage(const ErrorCondition _eCondition,const ParamValue & _rParamValue1,const ParamValue & _rParamValue2,const ParamValue & _rParamValue3) const310     ::rtl::OUString SQLError::getErrorMessage( const ErrorCondition _eCondition, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) const
311     {
312         return m_pImpl->getErrorMessage( _eCondition, _rParamValue1, _rParamValue2, _rParamValue3 );
313     }
314 
315     //--------------------------------------------------------------------
getSQLState(const ErrorCondition _eCondition) const316     ::rtl::OUString SQLError::getSQLState( const ErrorCondition _eCondition ) const
317     {
318         return m_pImpl->getSQLState( _eCondition );
319     }
320 
321     //--------------------------------------------------------------------
getErrorCode(const ErrorCondition _eCondition)322     ErrorCode SQLError::getErrorCode( const ErrorCondition _eCondition )
323     {
324         return SQLError_Impl::getErrorCode( _eCondition );
325     }
326 
327     //--------------------------------------------------------------------
raiseException(const ErrorCondition _eCondition,const Reference<XInterface> & _rxContext,const ParamValue & _rParamValue1,const ParamValue & _rParamValue2,const ParamValue & _rParamValue3) const328     void SQLError::raiseException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) const
329     {
330         m_pImpl->raiseException( _eCondition, _rxContext, _rParamValue1, _rParamValue2, _rParamValue3 );
331     }
332 
333     //--------------------------------------------------------------------
raiseException(const ErrorCondition _eCondition,const ParamValue & _rParamValue1,const ParamValue & _rParamValue2,const ParamValue & _rParamValue3) const334     void SQLError::raiseException( const ErrorCondition _eCondition, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) const
335     {
336         m_pImpl->raiseException( _eCondition, _rParamValue1, _rParamValue2, _rParamValue3 );
337     }
338 
339     //--------------------------------------------------------------------
raiseTypedException(const ErrorCondition _eCondition,const Reference<XInterface> & _rxContext,const Type & _rExceptionType,const ParamValue & _rParamValue1,const ParamValue & _rParamValue2,const ParamValue & _rParamValue3) const340     void SQLError::raiseTypedException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext,
341         const Type& _rExceptionType, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) const
342     {
343         m_pImpl->raiseTypedException( _eCondition, _rxContext, _rExceptionType, _rParamValue1, _rParamValue2, _rParamValue3 );
344     }
345 
346     //--------------------------------------------------------------------
getSQLException(const ErrorCondition _eCondition,const Reference<XInterface> & _rxContext,const ParamValue & _rParamValue1,const ParamValue & _rParamValue2,const ParamValue & _rParamValue3) const347     SQLException SQLError::getSQLException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext,
348         const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) const
349     {
350         return m_pImpl->getSQLException( _eCondition, _rxContext, _rParamValue1, _rParamValue2, _rParamValue3 );
351     }
352 
353 } // namespace connectivity
354 
355 /* vim: set noet sw=4 ts=4: */
356