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