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