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