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