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 //-------------------------------------------------------------------- 106 SQLError_Impl::SQLError_Impl( const ::comphelper::ComponentContext& _rContext ) 107 :m_aContext( _rContext ) 108 ,m_pResources( ) 109 ,m_bAttemptedInit( false ) 110 { 111 } 112 113 //-------------------------------------------------------------------- 114 SQLError_Impl::~SQLError_Impl() 115 { 116 } 117 118 //-------------------------------------------------------------------- 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 */ 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 //................................................................ 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 //-------------------------------------------------------------------- 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 //-------------------------------------------------------------------- 166 ::rtl::OUString SQLError_Impl::getSQLState( const ErrorCondition _eCondition ) 167 { 168 return impl_getSQLState( _eCondition ); 169 } 170 171 //-------------------------------------------------------------------- 172 ErrorCode SQLError_Impl::getErrorCode( const ErrorCondition _eCondition ) 173 { 174 return 0 - ::sal::static_int_cast< ErrorCode, ErrorCondition >( _eCondition ); 175 } 176 177 //-------------------------------------------------------------------- 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 //-------------------------------------------------------------------- 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 //-------------------------------------------------------------------- 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 //-------------------------------------------------------------------- 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 //-------------------------------------------------------------------- 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 //-------------------------------------------------------------------- 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 //-------------------------------------------------------------------- 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 //-------------------------------------------------------------------- 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 //-------------------------------------------------------------------- 293 SQLError::SQLError( const ::comphelper::ComponentContext& _rContext ) 294 :m_pImpl( new SQLError_Impl( _rContext ) ) 295 { 296 } 297 298 //-------------------------------------------------------------------- 299 SQLError::~SQLError() 300 { 301 } 302 303 //-------------------------------------------------------------------- 304 const ::rtl::OUString& SQLError::getMessagePrefix() 305 { 306 return SQLError_Impl::getMessagePrefix(); 307 } 308 309 //-------------------------------------------------------------------- 310 ::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 //-------------------------------------------------------------------- 316 ::rtl::OUString SQLError::getSQLState( const ErrorCondition _eCondition ) const 317 { 318 return m_pImpl->getSQLState( _eCondition ); 319 } 320 321 //-------------------------------------------------------------------- 322 ErrorCode SQLError::getErrorCode( const ErrorCondition _eCondition ) 323 { 324 return SQLError_Impl::getErrorCode( _eCondition ); 325 } 326 327 //-------------------------------------------------------------------- 328 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 //-------------------------------------------------------------------- 334 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 //-------------------------------------------------------------------- 340 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 //-------------------------------------------------------------------- 347 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