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