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 "calc/CConnection.hxx" 31 #include "calc/CDatabaseMetaData.hxx" 32 #include "calc/CCatalog.hxx" 33 #ifndef _CONNECTIVITY_CALC_ODRIVER_HXX_ 34 #include "calc/CDriver.hxx" 35 #endif 36 #ifndef CONNECTIVITY_RESOURCE_CALC_HRC 37 #include "resource/calc_res.hrc" 38 #endif 39 #include "resource/sharedresources.hxx" 40 #include <com/sun/star/lang/DisposedException.hpp> 41 #include <com/sun/star/frame/XComponentLoader.hpp> 42 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> 43 #include <tools/urlobj.hxx> 44 #include "calc/CPreparedStatement.hxx" 45 #include "calc/CStatement.hxx" 46 #include <unotools/pathoptions.hxx> 47 #include <connectivity/dbexception.hxx> 48 #include <cppuhelper/exc_hlp.hxx> 49 #include <rtl/logfile.hxx> 50 51 using namespace connectivity::calc; 52 using namespace connectivity::file; 53 54 typedef connectivity::file::OConnection OConnection_BASE; 55 56 //------------------------------------------------------------------------------ 57 58 using namespace ::com::sun::star::uno; 59 using namespace ::com::sun::star::beans; 60 using namespace ::com::sun::star::sdbcx; 61 using namespace ::com::sun::star::sdbc; 62 using namespace ::com::sun::star::lang; 63 using namespace ::com::sun::star::frame; 64 using namespace ::com::sun::star::sheet; 65 66 // -------------------------------------------------------------------------------- 67 68 OCalcConnection::OCalcConnection(ODriver* _pDriver) : OConnection(_pDriver),m_nDocCount(0) 69 { 70 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcConnection::OCalcConnection" ); 71 // m_aFilenameExtension is not used 72 } 73 74 OCalcConnection::~OCalcConnection() 75 { 76 } 77 78 void OCalcConnection::construct(const ::rtl::OUString& url,const Sequence< PropertyValue >& info) 79 throw(SQLException) 80 { 81 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcConnection::construct" ); 82 // open file 83 84 sal_Int32 nLen = url.indexOf(':'); 85 nLen = url.indexOf(':',nLen+1); 86 ::rtl::OUString aDSN(url.copy(nLen+1)); 87 88 m_aFileName = aDSN; 89 INetURLObject aURL; 90 aURL.SetSmartProtocol(INET_PROT_FILE); 91 { 92 SvtPathOptions aPathOptions; 93 m_aFileName = aPathOptions.SubstituteVariable(m_aFileName); 94 } 95 aURL.SetSmartURL(m_aFileName); 96 if ( aURL.GetProtocol() == INET_PROT_NOT_VALID ) 97 { 98 // don't pass invalid URL to loadComponentFromURL 99 throw SQLException(); 100 } 101 m_aFileName = aURL.GetMainURL(INetURLObject::NO_DECODE); 102 103 m_sPassword = ::rtl::OUString(); 104 const char* pPwd = "password"; 105 106 const PropertyValue *pIter = info.getConstArray(); 107 const PropertyValue *pEnd = pIter + info.getLength(); 108 for(;pIter != pEnd;++pIter) 109 { 110 if(!pIter->Name.compareToAscii(pPwd)) 111 { 112 pIter->Value >>= m_sPassword; 113 break; 114 } 115 } // for(;pIter != pEnd;++pIter) 116 ODocHolder aDocHodler(this); // just to test that the doc can be loaded 117 acquireDoc(); 118 } 119 // ----------------------------------------------------------------------------- 120 Reference< XSpreadsheetDocument> OCalcConnection::acquireDoc() 121 { 122 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcConnection::acquireDoc" ); 123 if ( m_xDoc.is() ) 124 { 125 osl_incrementInterlockedCount(&m_nDocCount); 126 return m_xDoc; 127 } 128 // open read-only as long as updating isn't implemented 129 Sequence<PropertyValue> aArgs(2); 130 aArgs[0].Name = ::rtl::OUString::createFromAscii("Hidden"); 131 aArgs[0].Value <<= (sal_Bool) sal_True; 132 aArgs[1].Name = ::rtl::OUString::createFromAscii("ReadOnly"); 133 aArgs[1].Value <<= (sal_Bool) sal_True; 134 135 if ( m_sPassword.getLength() ) 136 { 137 const sal_Int32 nPos = aArgs.getLength(); 138 aArgs.realloc(nPos+1); 139 aArgs[nPos].Name = ::rtl::OUString::createFromAscii("Password"); 140 aArgs[nPos].Value <<= m_sPassword; 141 } 142 143 Reference< XComponentLoader > xDesktop( getDriver()->getFactory()->createInstance( 144 ::rtl::OUString::createFromAscii("com.sun.star.frame.Desktop")), UNO_QUERY ); 145 if (!xDesktop.is()) 146 { 147 OSL_ASSERT("no desktop"); 148 throw SQLException(); 149 } 150 Reference< XComponent > xComponent; 151 Any aLoaderException; 152 try 153 { 154 xComponent = xDesktop->loadComponentFromURL( 155 m_aFileName, ::rtl::OUString::createFromAscii("_blank"), 0, aArgs ); 156 } 157 catch( const Exception& ) 158 { 159 aLoaderException = ::cppu::getCaughtException(); 160 } 161 162 m_xDoc.set(xComponent, UNO_QUERY ); 163 164 // if the URL is not a spreadsheet document, throw the exception here 165 // instead of at the first access to it 166 if ( !m_xDoc.is() ) 167 { 168 Any aErrorDetails; 169 if ( aLoaderException.hasValue() ) 170 { 171 Exception aLoaderError; 172 OSL_VERIFY( aLoaderException >>= aLoaderError ); 173 174 SQLException aDetailException; 175 aDetailException.Message = m_aResources.getResourceStringWithSubstitution( 176 STR_LOAD_FILE_ERROR_MESSAGE, 177 "$exception_type$", aLoaderException.getValueTypeName(), 178 "$error_message$", aLoaderError.Message 179 ); 180 aErrorDetails <<= aDetailException; 181 } 182 183 const ::rtl::OUString sError( m_aResources.getResourceStringWithSubstitution( 184 STR_COULD_NOT_LOAD_FILE, 185 "$filename$", m_aFileName 186 ) ); 187 ::dbtools::throwGenericSQLException( sError, *this, aErrorDetails ); 188 } 189 osl_incrementInterlockedCount(&m_nDocCount); 190 return m_xDoc; 191 } 192 // ----------------------------------------------------------------------------- 193 void OCalcConnection::releaseDoc() 194 { 195 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcConnection::releaseDoc" ); 196 if ( osl_decrementInterlockedCount(&m_nDocCount) == 0 ) 197 ::comphelper::disposeComponent( m_xDoc ); 198 } 199 // ----------------------------------------------------------------------------- 200 void OCalcConnection::disposing() 201 { 202 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcConnection::disposing" ); 203 ::osl::MutexGuard aGuard(m_aMutex); 204 205 m_nDocCount = 0; 206 ::comphelper::disposeComponent( m_xDoc ); 207 208 OConnection::disposing(); 209 } 210 211 // XServiceInfo 212 // -------------------------------------------------------------------------------- 213 214 IMPLEMENT_SERVICE_INFO(OCalcConnection, "com.sun.star.sdbc.drivers.calc.Connection", "com.sun.star.sdbc.Connection") 215 216 // -------------------------------------------------------------------------------- 217 218 Reference< XDatabaseMetaData > SAL_CALL OCalcConnection::getMetaData( ) throw(SQLException, RuntimeException) 219 { 220 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcConnection::getMetaData" ); 221 ::osl::MutexGuard aGuard( m_aMutex ); 222 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 223 224 225 Reference< XDatabaseMetaData > xMetaData = m_xMetaData; 226 if(!xMetaData.is()) 227 { 228 xMetaData = new OCalcDatabaseMetaData(this); 229 m_xMetaData = xMetaData; 230 } 231 232 return xMetaData; 233 } 234 235 //------------------------------------------------------------------------------ 236 237 ::com::sun::star::uno::Reference< XTablesSupplier > OCalcConnection::createCatalog() 238 { 239 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcConnection::createCatalog" ); 240 ::osl::MutexGuard aGuard( m_aMutex ); 241 Reference< XTablesSupplier > xTab = m_xCatalog; 242 if(!xTab.is()) 243 { 244 OCalcCatalog *pCat = new OCalcCatalog(this); 245 xTab = pCat; 246 m_xCatalog = xTab; 247 } 248 return xTab; 249 } 250 251 // -------------------------------------------------------------------------------- 252 253 Reference< XStatement > SAL_CALL OCalcConnection::createStatement( ) throw(SQLException, RuntimeException) 254 { 255 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcConnection::createStatement" ); 256 ::osl::MutexGuard aGuard( m_aMutex ); 257 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 258 259 260 Reference< XStatement > xReturn = new OCalcStatement(this); 261 m_aStatements.push_back(WeakReferenceHelper(xReturn)); 262 return xReturn; 263 } 264 265 // -------------------------------------------------------------------------------- 266 267 Reference< XPreparedStatement > SAL_CALL OCalcConnection::prepareStatement( const ::rtl::OUString& sql ) 268 throw(SQLException, RuntimeException) 269 { 270 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcConnection::prepareStatement" ); 271 ::osl::MutexGuard aGuard( m_aMutex ); 272 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 273 274 275 OCalcPreparedStatement* pStmt = new OCalcPreparedStatement(this); 276 Reference< XPreparedStatement > xHoldAlive = pStmt; 277 pStmt->construct(sql); 278 m_aStatements.push_back(WeakReferenceHelper(*pStmt)); 279 return pStmt; 280 } 281 282 // -------------------------------------------------------------------------------- 283 284 Reference< XPreparedStatement > SAL_CALL OCalcConnection::prepareCall( const ::rtl::OUString& /*sql*/ ) 285 throw(SQLException, RuntimeException) 286 { 287 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcConnection::prepareCall" ); 288 ::osl::MutexGuard aGuard( m_aMutex ); 289 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 290 291 ::dbtools::throwFeatureNotImplementedException( "XConnection::prepareCall", *this ); 292 return NULL; 293 } 294 // ----------------------------------------------------------------------------- 295 296