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