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 <ado/ADriver.hxx>
21 #include <ado/AConnection.hxx>
22 #include <ado/Awrapadox.hxx>
23 #include <ado/ACatalog.hxx>
24 #include <ado/Awrapado.hxx>
25 #include <ado/adoimp.hxx>
26 #include <com/sun/star/lang/DisposedException.hpp>
27 #include <connectivity/dbexception.hxx>
28 #include <cppuhelper/supportsservice.hxx>
29 #include <strings.hrc>
30 #include <objbase.h>
31 
32 #include <resource/sharedresources.hxx>
33 
34 #include <memory>
35 
36 using namespace connectivity;
37 using namespace connectivity::ado;
38 using namespace com::sun::star::uno;
39 using namespace com::sun::star::lang;
40 using namespace com::sun::star::beans;
41 using namespace com::sun::star::sdbc;
42 using namespace com::sun::star::sdbcx;
43 
44 
ODriver(const css::uno::Reference<css::lang::XMultiServiceFactory> & _xORB)45 ODriver::ODriver(const css::uno::Reference< css::lang::XMultiServiceFactory >& _xORB)
46     : ODriver_BASE(m_aMutex)
47     ,m_xORB(_xORB)
48 {
49      if ( FAILED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)) )
50      {
51          CoUninitialize();
52          int h = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
53          (void)h;
54          ++h;
55      }
56 }
57 
~ODriver()58 ODriver::~ODriver()
59 {
60     CoUninitialize();
61     CoInitialize(nullptr);
62 }
63 
disposing()64 void ODriver::disposing()
65 {
66     ::osl::MutexGuard aGuard(m_aMutex);
67 
68 
69     for (auto& rxConnection : m_xConnections)
70     {
71         Reference< XComponent > xComp(rxConnection.get(), UNO_QUERY);
72         if (xComp.is())
73             xComp->dispose();
74     }
75     m_xConnections.clear();
76 
77     ODriver_BASE::disposing();
78 }
79 // static ServiceInfo
80 
getImplementationName_Static()81 OUString ODriver::getImplementationName_Static(  )
82 {
83     return "com.sun.star.comp.sdbc.ado.ODriver";
84 }
85 
getSupportedServiceNames_Static()86 Sequence< OUString > ODriver::getSupportedServiceNames_Static(  )
87 {
88     return { "com.sun.star.sdbc.Driver", "com.sun.star.sdbcx.Driver" };
89 }
90 
ODriver_CreateInstance(const css::uno::Reference<css::lang::XMultiServiceFactory> & _rxFactory)91 css::uno::Reference< css::uno::XInterface > connectivity::ado::ODriver_CreateInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& _rxFactory)
92 {
93     return *(new ODriver(_rxFactory));
94 }
95 
96 
getImplementationName()97 OUString SAL_CALL ODriver::getImplementationName(  )
98 {
99     return getImplementationName_Static();
100 }
101 
supportsService(const OUString & _rServiceName)102 sal_Bool SAL_CALL ODriver::supportsService( const OUString& _rServiceName )
103 {
104     return cppu::supportsService(this, _rServiceName);
105 }
106 
107 
getSupportedServiceNames()108 Sequence< OUString > SAL_CALL ODriver::getSupportedServiceNames(  )
109 {
110     return getSupportedServiceNames_Static();
111 }
112 
113 
connect(const OUString & url,const Sequence<PropertyValue> & info)114 Reference< XConnection > SAL_CALL ODriver::connect( const OUString& url, const Sequence< PropertyValue >& info )
115 {
116     if ( ! acceptsURL(url) )
117         return nullptr;
118 
119     // we need to wrap the connection as the construct call might throw
120     std::unique_ptr<OConnection> pCon(new OConnection(this));
121     pCon->construct(url,info);
122     OConnection* pPtr = pCon.get();
123     Reference< XConnection > xCon = pCon.release();
124     m_xConnections.push_back(WeakReferenceHelper(*pPtr));
125 
126     return xCon;
127 }
128 
acceptsURL(const OUString & url)129 sal_Bool SAL_CALL ODriver::acceptsURL( const OUString& url )
130 {
131     return url.startsWith("sdbc:ado:");
132 }
133 
impl_checkURL_throw(const OUString & _sUrl)134 void ODriver::impl_checkURL_throw(const OUString& _sUrl)
135 {
136     if ( !acceptsURL(_sUrl) )
137     {
138         SharedResources aResources;
139         const OUString sMessage = aResources.getResourceString(STR_URI_SYNTAX_ERROR);
140         ::dbtools::throwGenericSQLException(sMessage ,*this);
141     } // if ( !acceptsURL(_sUrl) )
142 }
143 
getPropertyInfo(const OUString & url,const Sequence<PropertyValue> &)144 Sequence< DriverPropertyInfo > SAL_CALL ODriver::getPropertyInfo( const OUString& url, const Sequence< PropertyValue >& /*info*/ )
145 {
146     impl_checkURL_throw(url);
147     if ( acceptsURL(url) )
148     {
149         std::vector< DriverPropertyInfo > aDriverInfo;
150 
151         Sequence< OUString > aBooleanValues(2);
152         aBooleanValues[0] = "false";
153         aBooleanValues[1] = "true";
154 
155         aDriverInfo.push_back(DriverPropertyInfo(
156                 "IgnoreDriverPrivileges"
157                 ,"Ignore the privileges from the database driver."
158                 ,false
159                 ,"false"
160                 ,aBooleanValues)
161         );
162         aDriverInfo.push_back(DriverPropertyInfo(
163                 "EscapeDateTime"
164                 ,"Escape date time format."
165                 ,false
166                 ,"true"
167                 ,aBooleanValues)
168         );
169         aDriverInfo.push_back(DriverPropertyInfo(
170                 "TypeInfoSettings"
171                 ,"Defines how the type info of the database metadata should be manipulated."
172                 ,false
173                 ,OUString( )
174                 ,Sequence< OUString > ())
175         );
176         return Sequence< DriverPropertyInfo >(aDriverInfo.data(),aDriverInfo.size());
177     }
178     return Sequence< DriverPropertyInfo >();
179 }
180 
getMajorVersion()181 sal_Int32 SAL_CALL ODriver::getMajorVersion(  )
182 {
183     return 1;
184 }
185 
getMinorVersion()186 sal_Int32 SAL_CALL ODriver::getMinorVersion(  )
187 {
188     return 0;
189 }
190 
191 // XDataDefinitionSupplier
getDataDefinitionByConnection(const Reference<css::sdbc::XConnection> & connection)192 Reference< XTablesSupplier > SAL_CALL ODriver::getDataDefinitionByConnection( const Reference< css::sdbc::XConnection >& connection )
193 {
194     ::osl::MutexGuard aGuard( m_aMutex );
195     if (ODriver_BASE::rBHelper.bDisposed)
196         throw DisposedException();
197 
198     OConnection* pConnection = nullptr;
199     Reference< css::lang::XUnoTunnel> xTunnel(connection,UNO_QUERY);
200     if(xTunnel.is())
201     {
202         OConnection* pSearchConnection = reinterpret_cast< OConnection* >( xTunnel->getSomething(OConnection::getUnoTunnelId()) );
203 
204         auto foundConnection = std::any_of(m_xConnections.begin(), m_xConnections.end(),
205             [&pSearchConnection](const css::uno::WeakReferenceHelper& rxConnection) {
206                 return static_cast<OConnection*>(Reference< XConnection >::query(rxConnection.get().get()).get()) == pSearchConnection; });
207         if (foundConnection)
208             pConnection = pSearchConnection;
209     }
210 
211     Reference< XTablesSupplier > xTab;
212     if(pConnection)
213     {
214         WpADOCatalog aCatalog;
215         aCatalog.Create();
216         if(aCatalog.IsValid())
217         {
218             aCatalog.putref_ActiveConnection(*pConnection->getConnection());
219             OCatalog* pCatalog = new OCatalog(aCatalog,pConnection);
220             xTab = pCatalog;
221             pConnection->setCatalog(xTab);
222             pConnection->setCatalog(pCatalog);
223         }
224     }
225     return xTab;
226 }
227 
getDataDefinitionByURL(const OUString & url,const Sequence<PropertyValue> & info)228 Reference< XTablesSupplier > SAL_CALL ODriver::getDataDefinitionByURL( const OUString& url, const Sequence< PropertyValue >& info )
229 {
230     impl_checkURL_throw(url);
231     return getDataDefinitionByConnection(connect(url,info));
232 }
233 
234 
ThrowException(ADOConnection * _pAdoCon,const Reference<XInterface> & _xInterface)235 void ADOS::ThrowException(ADOConnection* _pAdoCon,const Reference< XInterface >& _xInterface)
236 {
237     ADOErrors *pErrors = nullptr;
238     _pAdoCon->get_Errors(&pErrors);
239     if(!pErrors)
240         return; // no error found
241 
242     pErrors->AddRef( );
243 
244     // read all noted errors and issue them
245     sal_Int32 nLen;
246     pErrors->get_Count(&nLen);
247     if (nLen)
248     {
249         SQLException aException;
250         aException.ErrorCode = 1000;
251         for (sal_Int32 i = nLen-1; i>=0; --i)
252         {
253             ADOError *pError = nullptr;
254             pErrors->get_Item(OLEVariant(i),&pError);
255             WpADOError aErr(pError);
256             OSL_ENSURE(pError,"No error in collection found! BAD!");
257             if(pError)
258             {
259                 if(i==nLen-1)
260                     aException = SQLException(aErr.GetDescription(),_xInterface,aErr.GetSQLState(),aErr.GetNumber(),Any());
261                 else
262                 {
263                     SQLException aTemp(aErr.GetDescription(),
264                         _xInterface,aErr.GetSQLState(),aErr.GetNumber(),makeAny(aException));
265                     aTemp.NextException <<= aException;
266                     aException = aTemp;
267                 }
268             }
269         }
270         pErrors->Clear();
271         pErrors->Release();
272         throw aException;
273     }
274     pErrors->Release();
275 }
276 
277 
278 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
279