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