1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_connectivity.hxx"
26*b1cdbd2cSJim Jagielski #ifndef _CONNECTIVITY_CONNECTIONWRAPPER_HXX_
27*b1cdbd2cSJim Jagielski #include "connectivity/ConnectionWrapper.hxx"
28*b1cdbd2cSJim Jagielski #endif
29*b1cdbd2cSJim Jagielski #include <com/sun/star/sdbc/ColumnValue.hpp>
30*b1cdbd2cSJim Jagielski #include <com/sun/star/sdbc/XRow.hpp>
31*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/DisposedException.hpp>
32*b1cdbd2cSJim Jagielski #include <comphelper/uno3.hxx>
33*b1cdbd2cSJim Jagielski #include <comphelper/sequence.hxx>
34*b1cdbd2cSJim Jagielski #include <cppuhelper/typeprovider.hxx>
35*b1cdbd2cSJim Jagielski #include <com/sun/star/reflection/XProxyFactory.hpp>
36*b1cdbd2cSJim Jagielski #include <rtl/digest.h>
37*b1cdbd2cSJim Jagielski #include <algorithm>
38*b1cdbd2cSJim Jagielski 
39*b1cdbd2cSJim Jagielski #include <algorithm>
40*b1cdbd2cSJim Jagielski 
41*b1cdbd2cSJim Jagielski using namespace connectivity;
42*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
43*b1cdbd2cSJim Jagielski using namespace com::sun::star::uno;
44*b1cdbd2cSJim Jagielski using namespace com::sun::star::lang;
45*b1cdbd2cSJim Jagielski using namespace com::sun::star::beans;
46*b1cdbd2cSJim Jagielski using namespace com::sun::star::sdbc;
47*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::reflection;
48*b1cdbd2cSJim Jagielski // --------------------------------------------------------------------------------
OConnectionWrapper()49*b1cdbd2cSJim Jagielski OConnectionWrapper::OConnectionWrapper()
50*b1cdbd2cSJim Jagielski {
51*b1cdbd2cSJim Jagielski 
52*b1cdbd2cSJim Jagielski }
53*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------------
setDelegation(Reference<XAggregation> & _rxProxyConnection,oslInterlockedCount & _rRefCount)54*b1cdbd2cSJim Jagielski void OConnectionWrapper::setDelegation(Reference< XAggregation >& _rxProxyConnection,oslInterlockedCount& _rRefCount)
55*b1cdbd2cSJim Jagielski {
56*b1cdbd2cSJim Jagielski 	OSL_ENSURE(_rxProxyConnection.is(),"OConnectionWrapper: Connection must be valid!");
57*b1cdbd2cSJim Jagielski 	osl_incrementInterlockedCount( &_rRefCount );
58*b1cdbd2cSJim Jagielski 	if (_rxProxyConnection.is())
59*b1cdbd2cSJim Jagielski 	{
60*b1cdbd2cSJim Jagielski 		// transfer the (one and only) real ref to the aggregate to our member
61*b1cdbd2cSJim Jagielski 		m_xProxyConnection = _rxProxyConnection;
62*b1cdbd2cSJim Jagielski 		_rxProxyConnection = NULL;
63*b1cdbd2cSJim Jagielski 		::comphelper::query_aggregation(m_xProxyConnection,m_xConnection);
64*b1cdbd2cSJim Jagielski 		m_xTypeProvider.set(m_xConnection,UNO_QUERY);
65*b1cdbd2cSJim Jagielski 		m_xUnoTunnel.set(m_xConnection,UNO_QUERY);
66*b1cdbd2cSJim Jagielski 		m_xServiceInfo.set(m_xConnection,UNO_QUERY);
67*b1cdbd2cSJim Jagielski 
68*b1cdbd2cSJim Jagielski 		// set ourself as delegator
69*b1cdbd2cSJim Jagielski 		Reference<XInterface> xIf = static_cast< XUnoTunnel* >( this );
70*b1cdbd2cSJim Jagielski 		m_xProxyConnection->setDelegator( xIf );
71*b1cdbd2cSJim Jagielski 
72*b1cdbd2cSJim Jagielski 	}
73*b1cdbd2cSJim Jagielski 	osl_decrementInterlockedCount( &_rRefCount );
74*b1cdbd2cSJim Jagielski }
75*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------------
setDelegation(const Reference<XConnection> & _xConnection,const Reference<XMultiServiceFactory> & _xORB,oslInterlockedCount & _rRefCount)76*b1cdbd2cSJim Jagielski void OConnectionWrapper::setDelegation(const Reference< XConnection >& _xConnection
77*b1cdbd2cSJim Jagielski 									   ,const Reference< XMultiServiceFactory>& _xORB
78*b1cdbd2cSJim Jagielski 									   ,oslInterlockedCount& _rRefCount)
79*b1cdbd2cSJim Jagielski {
80*b1cdbd2cSJim Jagielski 	OSL_ENSURE(_xConnection.is(),"OConnectionWrapper: Connection must be valid!");
81*b1cdbd2cSJim Jagielski 	osl_incrementInterlockedCount( &_rRefCount );
82*b1cdbd2cSJim Jagielski 
83*b1cdbd2cSJim Jagielski 	m_xConnection = _xConnection;
84*b1cdbd2cSJim Jagielski 	m_xTypeProvider.set(m_xConnection,UNO_QUERY);
85*b1cdbd2cSJim Jagielski 	m_xUnoTunnel.set(m_xConnection,UNO_QUERY);
86*b1cdbd2cSJim Jagielski 	m_xServiceInfo.set(m_xConnection,UNO_QUERY);
87*b1cdbd2cSJim Jagielski 
88*b1cdbd2cSJim Jagielski 	Reference< XProxyFactory >	xProxyFactory(_xORB->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.ProxyFactory"))),UNO_QUERY);
89*b1cdbd2cSJim Jagielski 	Reference< XAggregation > xConProxy = xProxyFactory->createProxy(_xConnection);
90*b1cdbd2cSJim Jagielski 	if (xConProxy.is())
91*b1cdbd2cSJim Jagielski 	{
92*b1cdbd2cSJim Jagielski 		// transfer the (one and only) real ref to the aggregate to our member
93*b1cdbd2cSJim Jagielski 		m_xProxyConnection = xConProxy;
94*b1cdbd2cSJim Jagielski 
95*b1cdbd2cSJim Jagielski 		// set ourself as delegator
96*b1cdbd2cSJim Jagielski 		Reference<XInterface> xIf = static_cast< XUnoTunnel* >( this );
97*b1cdbd2cSJim Jagielski 		m_xProxyConnection->setDelegator( xIf );
98*b1cdbd2cSJim Jagielski 
99*b1cdbd2cSJim Jagielski 	}
100*b1cdbd2cSJim Jagielski 	osl_decrementInterlockedCount( &_rRefCount );
101*b1cdbd2cSJim Jagielski }
102*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------------
disposing()103*b1cdbd2cSJim Jagielski void OConnectionWrapper::disposing()
104*b1cdbd2cSJim Jagielski {
105*b1cdbd2cSJim Jagielski m_xConnection.clear();
106*b1cdbd2cSJim Jagielski }
107*b1cdbd2cSJim Jagielski //-----------------------------------------------------------------------------
~OConnectionWrapper()108*b1cdbd2cSJim Jagielski OConnectionWrapper::~OConnectionWrapper()
109*b1cdbd2cSJim Jagielski {
110*b1cdbd2cSJim Jagielski 	if (m_xProxyConnection.is())
111*b1cdbd2cSJim Jagielski 		m_xProxyConnection->setDelegator(NULL);
112*b1cdbd2cSJim Jagielski }
113*b1cdbd2cSJim Jagielski 
114*b1cdbd2cSJim Jagielski // XServiceInfo
115*b1cdbd2cSJim Jagielski // --------------------------------------------------------------------------------
getImplementationName()116*b1cdbd2cSJim Jagielski ::rtl::OUString SAL_CALL OConnectionWrapper::getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException)
117*b1cdbd2cSJim Jagielski {
118*b1cdbd2cSJim Jagielski 	return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdbc.drivers.OConnectionWrapper" ) );
119*b1cdbd2cSJim Jagielski }
120*b1cdbd2cSJim Jagielski 
121*b1cdbd2cSJim Jagielski // --------------------------------------------------------------------------------
getSupportedServiceNames()122*b1cdbd2cSJim Jagielski ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL OConnectionWrapper::getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException)
123*b1cdbd2cSJim Jagielski {
124*b1cdbd2cSJim Jagielski 	// first collect the services which are supported by our aggregate
125*b1cdbd2cSJim Jagielski 	Sequence< ::rtl::OUString > aSupported;
126*b1cdbd2cSJim Jagielski 	if ( m_xServiceInfo.is() )
127*b1cdbd2cSJim Jagielski 		aSupported = m_xServiceInfo->getSupportedServiceNames();
128*b1cdbd2cSJim Jagielski 
129*b1cdbd2cSJim Jagielski 	// append our own service, if necessary
130*b1cdbd2cSJim Jagielski 	::rtl::OUString sConnectionService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdbc.Connection" ) );
131*b1cdbd2cSJim Jagielski 	if ( 0 == ::comphelper::findValue( aSupported, sConnectionService, sal_True ).getLength() )
132*b1cdbd2cSJim Jagielski 	{
133*b1cdbd2cSJim Jagielski 		sal_Int32 nLen = aSupported.getLength();
134*b1cdbd2cSJim Jagielski 		aSupported.realloc( nLen + 1 );
135*b1cdbd2cSJim Jagielski 		aSupported[ nLen ] = sConnectionService;
136*b1cdbd2cSJim Jagielski 	}
137*b1cdbd2cSJim Jagielski 
138*b1cdbd2cSJim Jagielski 	// outta here
139*b1cdbd2cSJim Jagielski 	return aSupported;
140*b1cdbd2cSJim Jagielski }
141*b1cdbd2cSJim Jagielski 
142*b1cdbd2cSJim Jagielski // --------------------------------------------------------------------------------
supportsService(const::rtl::OUString & _rServiceName)143*b1cdbd2cSJim Jagielski sal_Bool SAL_CALL OConnectionWrapper::supportsService( const ::rtl::OUString& _rServiceName ) throw(::com::sun::star::uno::RuntimeException)
144*b1cdbd2cSJim Jagielski {
145*b1cdbd2cSJim Jagielski 	return ::comphelper::findValue( getSupportedServiceNames(), _rServiceName, sal_True ).getLength() != 0;
146*b1cdbd2cSJim Jagielski }
147*b1cdbd2cSJim Jagielski 
148*b1cdbd2cSJim Jagielski // --------------------------------------------------------------------------------
queryInterface(const Type & _rType)149*b1cdbd2cSJim Jagielski Any SAL_CALL OConnectionWrapper::queryInterface( const Type& _rType ) throw (RuntimeException)
150*b1cdbd2cSJim Jagielski {
151*b1cdbd2cSJim Jagielski 	Any aReturn = OConnection_BASE::queryInterface(_rType);
152*b1cdbd2cSJim Jagielski 	return aReturn.hasValue() ? aReturn : (m_xProxyConnection.is() ? m_xProxyConnection->queryAggregation(_rType) : aReturn);
153*b1cdbd2cSJim Jagielski }
154*b1cdbd2cSJim Jagielski // --------------------------------------------------------------------------------
getTypes()155*b1cdbd2cSJim Jagielski Sequence< Type > SAL_CALL OConnectionWrapper::getTypes(  ) throw (::com::sun::star::uno::RuntimeException)
156*b1cdbd2cSJim Jagielski {
157*b1cdbd2cSJim Jagielski 	return ::comphelper::concatSequences(
158*b1cdbd2cSJim Jagielski 		OConnection_BASE::getTypes(),
159*b1cdbd2cSJim Jagielski 		m_xTypeProvider->getTypes()
160*b1cdbd2cSJim Jagielski 	);
161*b1cdbd2cSJim Jagielski }
162*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------------
163*b1cdbd2cSJim Jagielski // com::sun::star::lang::XUnoTunnel
getSomething(const Sequence<sal_Int8> & rId)164*b1cdbd2cSJim Jagielski sal_Int64 SAL_CALL OConnectionWrapper::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException)
165*b1cdbd2cSJim Jagielski {
166*b1cdbd2cSJim Jagielski 	if (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(),  rId.getConstArray(), 16 ) )
167*b1cdbd2cSJim Jagielski 		return reinterpret_cast< sal_Int64 >( this );
168*b1cdbd2cSJim Jagielski 
169*b1cdbd2cSJim Jagielski 	if(m_xUnoTunnel.is())
170*b1cdbd2cSJim Jagielski 		return m_xUnoTunnel->getSomething(rId);
171*b1cdbd2cSJim Jagielski 	return 0;
172*b1cdbd2cSJim Jagielski }
173*b1cdbd2cSJim Jagielski 
174*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------------
getUnoTunnelImplementationId()175*b1cdbd2cSJim Jagielski Sequence< sal_Int8 > OConnectionWrapper::getUnoTunnelImplementationId()
176*b1cdbd2cSJim Jagielski {
177*b1cdbd2cSJim Jagielski 	static ::cppu::OImplementationId * pId = 0;
178*b1cdbd2cSJim Jagielski 	if (! pId)
179*b1cdbd2cSJim Jagielski 	{
180*b1cdbd2cSJim Jagielski 		::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
181*b1cdbd2cSJim Jagielski 		if (! pId)
182*b1cdbd2cSJim Jagielski 		{
183*b1cdbd2cSJim Jagielski 			static ::cppu::OImplementationId aId;
184*b1cdbd2cSJim Jagielski 			pId = &aId;
185*b1cdbd2cSJim Jagielski 		}
186*b1cdbd2cSJim Jagielski 	}
187*b1cdbd2cSJim Jagielski 	return pId->getImplementationId();
188*b1cdbd2cSJim Jagielski }
189*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------------
190*b1cdbd2cSJim Jagielski namespace
191*b1cdbd2cSJim Jagielski {
192*b1cdbd2cSJim Jagielski 	class TPropertyValueLessFunctor : public ::std::binary_function< ::com::sun::star::beans::PropertyValue,::com::sun::star::beans::PropertyValue,bool>
193*b1cdbd2cSJim Jagielski 	{
194*b1cdbd2cSJim Jagielski 	public:
TPropertyValueLessFunctor()195*b1cdbd2cSJim Jagielski 		TPropertyValueLessFunctor()
196*b1cdbd2cSJim Jagielski 		{}
operator ()(const::com::sun::star::beans::PropertyValue & lhs,const::com::sun::star::beans::PropertyValue & rhs) const197*b1cdbd2cSJim Jagielski 		bool operator() (const ::com::sun::star::beans::PropertyValue& lhs, const ::com::sun::star::beans::PropertyValue& rhs) const
198*b1cdbd2cSJim Jagielski 		{
199*b1cdbd2cSJim Jagielski 			const rtl_uString* l = lhs.Name.pData;
200*b1cdbd2cSJim Jagielski 			const rtl_uString* r = rhs.Name.pData;
201*b1cdbd2cSJim Jagielski 			const int c = rtl_ustr_compareIgnoreAsciiCase_WithLength( l->buffer, l->length, r->buffer, r->length );
202*b1cdbd2cSJim Jagielski 			return (c < 0);
203*b1cdbd2cSJim Jagielski 		}
204*b1cdbd2cSJim Jagielski 	};
205*b1cdbd2cSJim Jagielski 
206*b1cdbd2cSJim Jagielski }
207*b1cdbd2cSJim Jagielski 
208*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------------
209*b1cdbd2cSJim Jagielski // creates a unique id out of the url and sequence of properties
createUniqueId(const::rtl::OUString & _rURL,Sequence<PropertyValue> & _rInfo,sal_uInt8 * _pBuffer,const::rtl::OUString & _rUserName,const::rtl::OUString & _rPassword)210*b1cdbd2cSJim Jagielski void OConnectionWrapper::createUniqueId( const ::rtl::OUString& _rURL
211*b1cdbd2cSJim Jagielski 					,Sequence< PropertyValue >& _rInfo
212*b1cdbd2cSJim Jagielski 					,sal_uInt8* _pBuffer
213*b1cdbd2cSJim Jagielski 					,const ::rtl::OUString& _rUserName
214*b1cdbd2cSJim Jagielski 					,const ::rtl::OUString& _rPassword)
215*b1cdbd2cSJim Jagielski {
216*b1cdbd2cSJim Jagielski 	// first we create the digest we want to have
217*b1cdbd2cSJim Jagielski 	rtlDigest aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
218*b1cdbd2cSJim Jagielski 	rtlDigestError aError = rtl_digest_update(aDigest,_rURL.getStr(),_rURL.getLength()*sizeof(sal_Unicode));
219*b1cdbd2cSJim Jagielski 	if ( _rUserName.getLength() )
220*b1cdbd2cSJim Jagielski 		aError = rtl_digest_update(aDigest,_rUserName.getStr(),_rUserName.getLength()*sizeof(sal_Unicode));
221*b1cdbd2cSJim Jagielski 	if ( _rPassword.getLength() )
222*b1cdbd2cSJim Jagielski 		aError = rtl_digest_update(aDigest,_rPassword.getStr(),_rPassword.getLength()*sizeof(sal_Unicode));
223*b1cdbd2cSJim Jagielski 	// now we need to sort the properties
224*b1cdbd2cSJim Jagielski 	PropertyValue* pBegin = _rInfo.getArray();
225*b1cdbd2cSJim Jagielski 	PropertyValue* pEnd   = pBegin + _rInfo.getLength();
226*b1cdbd2cSJim Jagielski 	::std::sort(pBegin,pEnd,TPropertyValueLessFunctor());
227*b1cdbd2cSJim Jagielski 
228*b1cdbd2cSJim Jagielski 	pBegin = _rInfo.getArray();
229*b1cdbd2cSJim Jagielski 	pEnd   = pBegin + _rInfo.getLength();
230*b1cdbd2cSJim Jagielski 	for (; pBegin != pEnd; ++pBegin)
231*b1cdbd2cSJim Jagielski 	{
232*b1cdbd2cSJim Jagielski 		// we only include strings an integer values
233*b1cdbd2cSJim Jagielski 		::rtl::OUString sValue;
234*b1cdbd2cSJim Jagielski 		if ( pBegin->Value >>= sValue )
235*b1cdbd2cSJim Jagielski 			;
236*b1cdbd2cSJim Jagielski 		else
237*b1cdbd2cSJim Jagielski 		{
238*b1cdbd2cSJim Jagielski 			sal_Int32 nValue = 0;
239*b1cdbd2cSJim Jagielski 			if ( pBegin->Value >>= nValue )
240*b1cdbd2cSJim Jagielski 				sValue = ::rtl::OUString::valueOf(nValue);
241*b1cdbd2cSJim Jagielski 			else
242*b1cdbd2cSJim Jagielski 			{
243*b1cdbd2cSJim Jagielski 				Sequence< ::rtl::OUString> aSeq;
244*b1cdbd2cSJim Jagielski 				if ( pBegin->Value >>= aSeq )
245*b1cdbd2cSJim Jagielski 				{
246*b1cdbd2cSJim Jagielski 					const ::rtl::OUString* pSBegin = aSeq.getConstArray();
247*b1cdbd2cSJim Jagielski 					const ::rtl::OUString* pSEnd   = pSBegin + aSeq.getLength();
248*b1cdbd2cSJim Jagielski 					for(;pSBegin != pSEnd;++pSBegin)
249*b1cdbd2cSJim Jagielski 						aError = rtl_digest_update(aDigest,pSBegin->getStr(),pSBegin->getLength()*sizeof(sal_Unicode));
250*b1cdbd2cSJim Jagielski 				}
251*b1cdbd2cSJim Jagielski 			}
252*b1cdbd2cSJim Jagielski 		}
253*b1cdbd2cSJim Jagielski 		if ( sValue.getLength() > 0 )
254*b1cdbd2cSJim Jagielski 		{
255*b1cdbd2cSJim Jagielski 			// we don't have to convert this into UTF8 because we don't store on a file system
256*b1cdbd2cSJim Jagielski 			aError = rtl_digest_update(aDigest,sValue.getStr(),sValue.getLength()*sizeof(sal_Unicode));
257*b1cdbd2cSJim Jagielski 		}
258*b1cdbd2cSJim Jagielski 	}
259*b1cdbd2cSJim Jagielski 
260*b1cdbd2cSJim Jagielski 	aError = rtl_digest_get(aDigest,_pBuffer,RTL_DIGEST_LENGTH_SHA1);
261*b1cdbd2cSJim Jagielski 	// we have to destroy the digest
262*b1cdbd2cSJim Jagielski 	rtl_digest_destroy(aDigest);
263*b1cdbd2cSJim Jagielski }
264*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------------
265*b1cdbd2cSJim Jagielski 
266*b1cdbd2cSJim Jagielski 
267