xref: /AOO41X/main/connectivity/source/drivers/file/FConnection.cxx (revision 9b5730f6ddef7eb82608ca4d31dc0d7678e652cf)
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