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 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_connectivity.hxx" 26 #include <cppuhelper/typeprovider.hxx> 27 #include "file/FConnection.hxx" 28 #include "file/FDatabaseMetaData.hxx" 29 #include "file/FDriver.hxx" 30 #include "file/FStatement.hxx" 31 #include "file/FPreparedStatement.hxx" 32 #include <com/sun/star/sdbc/ColumnValue.hpp> 33 #include <com/sun/star/sdbc/XRow.hpp> 34 #include <com/sun/star/lang/DisposedException.hpp> 35 #include <com/sun/star/container/XChild.hpp> 36 #include <com/sun/star/ucb/XContent.hpp> 37 #include <com/sun/star/ucb/XContentIdentifier.hpp> 38 #include <tools/urlobj.hxx> 39 #include "file/FCatalog.hxx" 40 #include <unotools/pathoptions.hxx> 41 #include <ucbhelper/content.hxx> 42 #include <connectivity/dbcharset.hxx> 43 #include <connectivity/dbexception.hxx> 44 #include <osl/thread.h> 45 #include <osl/nlsupport.h> 46 #include "resource/file_res.hrc" 47 48 using namespace connectivity::file; 49 using namespace dbtools; 50 //------------------------------------------------------------------------------ 51 using namespace com::sun::star::uno; 52 using namespace com::sun::star::lang; 53 using namespace com::sun::star::beans; 54 using namespace com::sun::star::sdbc; 55 using namespace com::sun::star::sdbcx; 56 using namespace com::sun::star::container; 57 using namespace com::sun::star::ucb; 58 using namespace ::ucbhelper; 59 using rtl::OUString; 60 typedef connectivity::OMetaConnection OConnection_BASE; 61 // -------------------------------------------------------------------------------- 62 OConnection::OConnection(OFileDriver* _pDriver) 63 : OSubComponent<OConnection, OConnection_BASE>((::cppu::OWeakObject*)_pDriver, this) 64 ,m_pDriver(_pDriver) 65 ,m_bClosed(sal_False) 66 ,m_bShowDeleted(sal_False) 67 ,m_bCaseSensitiveExtension( sal_True ) 68 ,m_bCheckSQL92(sal_False) 69 ,m_bDefaultTextEncoding(false) 70 { 71 m_nTextEncoding = RTL_TEXTENCODING_DONTKNOW; 72 } 73 //----------------------------------------------------------------------------- 74 OConnection::~OConnection() 75 { 76 if(!isClosed( )) 77 close(); 78 } 79 //----------------------------------------------------------------------------- 80 void SAL_CALL OConnection::release() throw() 81 { 82 relase_ChildImpl(); 83 } 84 85 //----------------------------------------------------------------------------- 86 sal_Bool OConnection::matchesExtension( const String& _rExt ) const 87 { 88 if ( isCaseSensitveExtension() ) 89 return ( getExtension() == _rExt ); 90 91 String sMyExtension( getExtension() ); 92 sMyExtension.ToLowerAscii(); 93 String sExt( _rExt ); 94 sExt.ToLowerAscii(); 95 96 return sMyExtension == sExt; 97 } 98 99 //----------------------------------------------------------------------------- 100 void OConnection::construct(const ::rtl::OUString& url,const Sequence< PropertyValue >& info) throw(SQLException) 101 { 102 osl_incrementInterlockedCount( &m_refCount ); 103 104 ::rtl::OUString aExt; 105 const PropertyValue *pIter = info.getConstArray(); 106 const PropertyValue *pEnd = pIter + info.getLength(); 107 for(;pIter != pEnd;++pIter) 108 { 109 if(0 == pIter->Name.compareToAscii("Extension")) 110 OSL_VERIFY( pIter->Value >>= aExt ); 111 else if(0 == pIter->Name.compareToAscii("CharSet")) 112 { 113 ::rtl::OUString sIanaName; 114 OSL_VERIFY( pIter->Value >>= sIanaName ); 115 116 ::dbtools::OCharsetMap aLookupIanaName; 117 ::dbtools::OCharsetMap::const_iterator aLookup = aLookupIanaName.find(sIanaName, ::dbtools::OCharsetMap::IANA()); 118 if (aLookup != aLookupIanaName.end()) 119 m_nTextEncoding = (*aLookup).getEncoding(); 120 else 121 m_nTextEncoding = RTL_TEXTENCODING_DONTKNOW; 122 } 123 else if (0 == pIter->Name.compareToAscii("ShowDeleted")) 124 { 125 OSL_VERIFY( pIter->Value >>= m_bShowDeleted ); 126 } 127 else if (0 == pIter->Name.compareToAscii("EnableSQL92Check")) 128 { 129 pIter->Value >>= m_bCheckSQL92; 130 } 131 } // for(;pIter != pEnd;++pIter) 132 133 { 134 sal_Int32 nLen = url.indexOf(':'); 135 nLen = url.indexOf(':',nLen+1); 136 ::rtl::OUString aDSN(url.copy(nLen+1)),aUID,aPWD; 137 138 String aFileName = aDSN; 139 INetURLObject aURL; 140 aURL.SetSmartProtocol(INET_PROT_FILE); 141 { 142 SvtPathOptions aPathOptions; 143 aFileName = aPathOptions.SubstituteVariable(aFileName); 144 } 145 146 aURL.SetSmartURL(aFileName); 147 148 setURL(aURL.GetMainURL(INetURLObject::NO_DECODE)); 149 } 150 151 if ( m_nTextEncoding == RTL_TEXTENCODING_DONTKNOW ) 152 { 153 //m_nTextEncoding = osl_getTextEncodingFromLocale(NULL); 154 m_nTextEncoding = osl_getThreadTextEncoding(); 155 m_bDefaultTextEncoding = true; 156 } 157 158 if ( aExt.getLength() ) 159 m_aFilenameExtension = aExt; 160 161 try 162 { 163 ::ucbhelper::Content aFile; 164 try 165 { 166 aFile = ::ucbhelper::Content(getURL(),Reference< XCommandEnvironment >()); 167 } 168 catch(ContentCreationException& e) 169 { 170 throwUrlNotValid(getURL(),e.Message); 171 } 172 173 // set fields to fetch 174 Sequence< OUString > aProps(1); 175 OUString* pProps = aProps.getArray(); 176 pProps[ 0 ] = OUString::createFromAscii( "Title" ); 177 178 try 179 { 180 if (aFile.isFolder()) 181 { 182 m_xDir = aFile.createDynamicCursor(aProps, ::ucbhelper::INCLUDE_DOCUMENTS_ONLY ); 183 m_xContent = aFile.get(); 184 } 185 else if (aFile.isDocument()) 186 { 187 Reference<XContent> xParent(Reference<XChild>(aFile.get(),UNO_QUERY)->getParent(),UNO_QUERY); 188 Reference<XContentIdentifier> xIdent = xParent->getIdentifier(); 189 m_xContent = xParent; 190 191 ::ucbhelper::Content aParent(xIdent->getContentIdentifier(),Reference< XCommandEnvironment >()); 192 m_xDir = aParent.createDynamicCursor(aProps, ::ucbhelper::INCLUDE_DOCUMENTS_ONLY ); 193 } 194 else 195 { 196 OSL_ENSURE(0,"OConnection::construct: ::ucbhelper::Content isn't a folde nor a document! How that?!"); 197 throw SQLException(); 198 } 199 } 200 catch(Exception& e) // a execption is thrown when no file exists 201 { 202 throwUrlNotValid(getURL(),e.Message); 203 } 204 if(!m_xDir.is() || !m_xContent.is()) 205 throwUrlNotValid(getURL(),::rtl::OUString()); 206 207 if (m_aFilenameExtension.Search('*') != STRING_NOTFOUND || m_aFilenameExtension.Search('?') != STRING_NOTFOUND) 208 throw SQLException(); 209 } 210 catch(const Exception&) 211 { 212 osl_decrementInterlockedCount( &m_refCount ); 213 throw; 214 } 215 216 osl_decrementInterlockedCount( &m_refCount ); 217 } 218 // XServiceInfo 219 // -------------------------------------------------------------------------------- 220 IMPLEMENT_SERVICE_INFO(OConnection, "com.sun.star.sdbc.drivers.file.Connection", "com.sun.star.sdbc.Connection") 221 222 // -------------------------------------------------------------------------------- 223 Reference< XStatement > SAL_CALL OConnection::createStatement( ) throw(SQLException, RuntimeException) 224 { 225 ::osl::MutexGuard aGuard( m_aMutex ); 226 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 227 228 229 Reference< XStatement > xReturn = new OStatement(this); 230 m_aStatements.push_back(WeakReferenceHelper(xReturn)); 231 return xReturn; 232 } 233 // -------------------------------------------------------------------------------- 234 Reference< XPreparedStatement > SAL_CALL OConnection::prepareStatement( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException) 235 { 236 ::osl::MutexGuard aGuard( m_aMutex ); 237 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 238 239 240 OPreparedStatement* pStmt = new OPreparedStatement(this); 241 Reference< XPreparedStatement > xHoldAlive = pStmt; 242 pStmt->construct(sql); 243 m_aStatements.push_back(WeakReferenceHelper(*pStmt)); 244 return pStmt; 245 } 246 // -------------------------------------------------------------------------------- 247 Reference< XPreparedStatement > SAL_CALL OConnection::prepareCall( const ::rtl::OUString& /*sql*/ ) throw(SQLException, RuntimeException) 248 { 249 throwFeatureNotImplementedException( "XConnection::prepareCall", *this ); 250 return NULL; 251 } 252 // -------------------------------------------------------------------------------- 253 ::rtl::OUString SAL_CALL OConnection::nativeSQL( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException) 254 { 255 return sql; 256 } 257 // -------------------------------------------------------------------------------- 258 void SAL_CALL OConnection::setAutoCommit( sal_Bool autoCommit ) throw(SQLException, RuntimeException) 259 { 260 ::osl::MutexGuard aGuard( m_aMutex ); 261 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 262 263 m_bAutoCommit = autoCommit; 264 } 265 // -------------------------------------------------------------------------------- 266 sal_Bool SAL_CALL OConnection::getAutoCommit( ) throw(SQLException, RuntimeException) 267 { 268 ::osl::MutexGuard aGuard( m_aMutex ); 269 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 270 271 return m_bAutoCommit; 272 } 273 // -------------------------------------------------------------------------------- 274 void SAL_CALL OConnection::commit( ) throw(SQLException, RuntimeException) 275 { 276 } 277 // -------------------------------------------------------------------------------- 278 void SAL_CALL OConnection::rollback( ) throw(SQLException, RuntimeException) 279 { 280 } 281 // -------------------------------------------------------------------------------- 282 sal_Bool SAL_CALL OConnection::isClosed( ) throw(SQLException, RuntimeException) 283 { 284 ::osl::MutexGuard aGuard( m_aMutex ); 285 286 return OConnection_BASE::rBHelper.bDisposed; 287 } 288 // -------------------------------------------------------------------------------- 289 Reference< XDatabaseMetaData > SAL_CALL OConnection::getMetaData( ) throw(SQLException, RuntimeException) 290 { 291 ::osl::MutexGuard aGuard( m_aMutex ); 292 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 293 294 295 Reference< XDatabaseMetaData > xMetaData = m_xMetaData; 296 if(!xMetaData.is()) 297 { 298 xMetaData = new ODatabaseMetaData(this); 299 m_xMetaData = xMetaData; 300 } 301 302 return xMetaData; 303 } 304 // -------------------------------------------------------------------------------- 305 void SAL_CALL OConnection::setReadOnly( sal_Bool readOnly ) throw(SQLException, RuntimeException) 306 { 307 ::osl::MutexGuard aGuard( m_aMutex ); 308 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 309 310 311 m_bReadOnly = readOnly; 312 } 313 // -------------------------------------------------------------------------------- 314 sal_Bool SAL_CALL OConnection::isReadOnly( ) throw(SQLException, RuntimeException) 315 { 316 ::osl::MutexGuard aGuard( m_aMutex ); 317 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 318 319 320 return m_bReadOnly; 321 } 322 // -------------------------------------------------------------------------------- 323 void SAL_CALL OConnection::setCatalog( const ::rtl::OUString& /*catalog*/ ) throw(SQLException, RuntimeException) 324 { 325 throwFeatureNotImplementedException( "XConnection::setCatalog", *this ); 326 } 327 // -------------------------------------------------------------------------------- 328 ::rtl::OUString SAL_CALL OConnection::getCatalog( ) throw(SQLException, RuntimeException) 329 { 330 return ::rtl::OUString(); 331 } 332 // -------------------------------------------------------------------------------- 333 void SAL_CALL OConnection::setTransactionIsolation( sal_Int32 /*level*/ ) throw(SQLException, RuntimeException) 334 { 335 throwFeatureNotImplementedException( "XConnection::setTransactionIsolation", *this ); 336 } 337 // -------------------------------------------------------------------------------- 338 sal_Int32 SAL_CALL OConnection::getTransactionIsolation( ) throw(SQLException, RuntimeException) 339 { 340 return 0; 341 } 342 // -------------------------------------------------------------------------------- 343 Reference< XNameAccess > SAL_CALL OConnection::getTypeMap( ) throw(SQLException, RuntimeException) 344 { 345 return NULL; 346 } 347 // -------------------------------------------------------------------------------- 348 void SAL_CALL OConnection::setTypeMap( const Reference< XNameAccess >& /*typeMap*/ ) throw(SQLException, RuntimeException) 349 { 350 } 351 // -------------------------------------------------------------------------------- 352 // XCloseable 353 void SAL_CALL OConnection::close( ) throw(SQLException, RuntimeException) 354 { 355 { 356 ::osl::MutexGuard aGuard( m_aMutex ); 357 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 358 359 } 360 dispose(); 361 } 362 // -------------------------------------------------------------------------------- 363 // XWarningsSupplier 364 Any SAL_CALL OConnection::getWarnings( ) throw(SQLException, RuntimeException) 365 { 366 return Any(); 367 } 368 // -------------------------------------------------------------------------------- 369 void SAL_CALL OConnection::clearWarnings( ) throw(SQLException, RuntimeException) 370 { 371 } 372 //------------------------------------------------------------------------------ 373 void OConnection::disposing() 374 { 375 ::osl::MutexGuard aGuard(m_aMutex); 376 OConnection_BASE::disposing(); 377 378 m_bClosed = sal_True; 379 m_xDir.clear(); 380 m_xContent.clear(); 381 m_xCatalog = WeakReference< XTablesSupplier>(); 382 383 dispose_ChildImpl(); 384 } 385 //------------------------------------------------------------------------------ 386 Reference< XTablesSupplier > OConnection::createCatalog() 387 { 388 ::osl::MutexGuard aGuard( m_aMutex ); 389 Reference< XTablesSupplier > xTab = m_xCatalog; 390 if(!xTab.is()) 391 { 392 xTab = new OFileCatalog(this); 393 m_xCatalog = xTab; 394 } 395 return xTab; 396 } 397 // ----------------------------------------------------------------------------- 398 Reference< XDynamicResultSet > OConnection::getDir() const 399 { 400 Reference<XDynamicResultSet> xContent; 401 Sequence< ::rtl::OUString > aProps(1); 402 ::rtl::OUString* pProps = aProps.getArray(); 403 pProps[ 0 ] = ::rtl::OUString::createFromAscii( "Title" ); 404 try 405 { 406 Reference<XContentIdentifier> xIdent = getContent()->getIdentifier(); 407 ::ucbhelper::Content aParent(xIdent->getContentIdentifier(),Reference< XCommandEnvironment >()); 408 xContent = aParent.createDynamicCursor(aProps, ::ucbhelper::INCLUDE_DOCUMENTS_ONLY ); 409 } 410 catch(Exception&) 411 { 412 } 413 return xContent; 414 } 415 // ----------------------------------------------------------------------------- 416 sal_Int64 SAL_CALL OConnection::getSomething( const Sequence< sal_Int8 >& rId ) throw (RuntimeException) 417 { 418 return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) 419 ? reinterpret_cast< sal_Int64 >( this ) 420 : (sal_Int64)0; 421 } 422 // ----------------------------------------------------------------------------- 423 Sequence< sal_Int8 > OConnection::getUnoTunnelImplementationId() 424 { 425 static ::cppu::OImplementationId * pId = 0; 426 if (! pId) 427 { 428 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 429 if (! pId) 430 { 431 static ::cppu::OImplementationId aId; 432 pId = &aId; 433 } 434 } 435 return pId->getImplementationId(); 436 } 437 // ----------------------------------------------------------------------------- 438 void OConnection::throwUrlNotValid(const ::rtl::OUString & _rsUrl,const ::rtl::OUString & _rsMessage) 439 { 440 SQLException aError; 441 aError.Message = getResources().getResourceStringWithSubstitution( 442 STR_NO_VALID_FILE_URL, 443 "$URL$", _rsUrl 444 ); 445 446 aError.SQLState = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("S1000")); 447 aError.ErrorCode = 0; 448 aError.Context = static_cast< XConnection* >(this); 449 if (_rsMessage.getLength()) 450 aError.NextException <<= SQLException(_rsMessage, aError.Context, ::rtl::OUString(), 0, Any()); 451 452 throw aError; 453 } 454 // ----------------------------------------------------------------------------- 455 456 457 458