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