xref: /trunk/main/connectivity/source/commontools/ConnectionWrapper.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 #ifndef _CONNECTIVITY_CONNECTIONWRAPPER_HXX_
31 #include "connectivity/ConnectionWrapper.hxx"
32 #endif
33 #include <com/sun/star/sdbc/ColumnValue.hpp>
34 #include <com/sun/star/sdbc/XRow.hpp>
35 #include <com/sun/star/lang/DisposedException.hpp>
36 #include <comphelper/uno3.hxx>
37 #include <comphelper/sequence.hxx>
38 #include <cppuhelper/typeprovider.hxx>
39 #include <com/sun/star/reflection/XProxyFactory.hpp>
40 #include <rtl/digest.h>
41 #include <algorithm>
42 
43 #include <algorithm>
44 
45 using namespace connectivity;
46 //------------------------------------------------------------------------------
47 using namespace com::sun::star::uno;
48 using namespace com::sun::star::lang;
49 using namespace com::sun::star::beans;
50 using namespace com::sun::star::sdbc;
51 using namespace ::com::sun::star::reflection;
52 // --------------------------------------------------------------------------------
53 OConnectionWrapper::OConnectionWrapper()
54 {
55 
56 }
57 // -----------------------------------------------------------------------------
58 void OConnectionWrapper::setDelegation(Reference< XAggregation >& _rxProxyConnection,oslInterlockedCount& _rRefCount)
59 {
60     OSL_ENSURE(_rxProxyConnection.is(),"OConnectionWrapper: Connection must be valid!");
61     osl_incrementInterlockedCount( &_rRefCount );
62     if (_rxProxyConnection.is())
63     {
64         // transfer the (one and only) real ref to the aggregate to our member
65         m_xProxyConnection = _rxProxyConnection;
66         _rxProxyConnection = NULL;
67         ::comphelper::query_aggregation(m_xProxyConnection,m_xConnection);
68         m_xTypeProvider.set(m_xConnection,UNO_QUERY);
69         m_xUnoTunnel.set(m_xConnection,UNO_QUERY);
70         m_xServiceInfo.set(m_xConnection,UNO_QUERY);
71 
72         // set ourself as delegator
73         Reference<XInterface> xIf = static_cast< XUnoTunnel* >( this );
74         m_xProxyConnection->setDelegator( xIf );
75 
76     }
77     osl_decrementInterlockedCount( &_rRefCount );
78 }
79 // -----------------------------------------------------------------------------
80 void OConnectionWrapper::setDelegation(const Reference< XConnection >& _xConnection
81                                        ,const Reference< XMultiServiceFactory>& _xORB
82                                        ,oslInterlockedCount& _rRefCount)
83 {
84     OSL_ENSURE(_xConnection.is(),"OConnectionWrapper: Connection must be valid!");
85     osl_incrementInterlockedCount( &_rRefCount );
86 
87     m_xConnection = _xConnection;
88     m_xTypeProvider.set(m_xConnection,UNO_QUERY);
89     m_xUnoTunnel.set(m_xConnection,UNO_QUERY);
90     m_xServiceInfo.set(m_xConnection,UNO_QUERY);
91 
92     Reference< XProxyFactory >  xProxyFactory(_xORB->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.ProxyFactory"))),UNO_QUERY);
93     Reference< XAggregation > xConProxy = xProxyFactory->createProxy(_xConnection);
94     if (xConProxy.is())
95     {
96         // transfer the (one and only) real ref to the aggregate to our member
97         m_xProxyConnection = xConProxy;
98 
99         // set ourself as delegator
100         Reference<XInterface> xIf = static_cast< XUnoTunnel* >( this );
101         m_xProxyConnection->setDelegator( xIf );
102 
103     }
104     osl_decrementInterlockedCount( &_rRefCount );
105 }
106 // -----------------------------------------------------------------------------
107 void OConnectionWrapper::disposing()
108 {
109 m_xConnection.clear();
110 }
111 //-----------------------------------------------------------------------------
112 OConnectionWrapper::~OConnectionWrapper()
113 {
114     if (m_xProxyConnection.is())
115         m_xProxyConnection->setDelegator(NULL);
116 }
117 
118 // XServiceInfo
119 // --------------------------------------------------------------------------------
120 ::rtl::OUString SAL_CALL OConnectionWrapper::getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException)
121 {
122     return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdbc.drivers.OConnectionWrapper" ) );
123 }
124 
125 // --------------------------------------------------------------------------------
126 ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL OConnectionWrapper::getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException)
127 {
128     // first collect the services which are supported by our aggregate
129     Sequence< ::rtl::OUString > aSupported;
130     if ( m_xServiceInfo.is() )
131         aSupported = m_xServiceInfo->getSupportedServiceNames();
132 
133     // append our own service, if necessary
134     ::rtl::OUString sConnectionService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdbc.Connection" ) );
135     if ( 0 == ::comphelper::findValue( aSupported, sConnectionService, sal_True ).getLength() )
136     {
137         sal_Int32 nLen = aSupported.getLength();
138         aSupported.realloc( nLen + 1 );
139         aSupported[ nLen ] = sConnectionService;
140     }
141 
142     // outta here
143     return aSupported;
144 }
145 
146 // --------------------------------------------------------------------------------
147 sal_Bool SAL_CALL OConnectionWrapper::supportsService( const ::rtl::OUString& _rServiceName ) throw(::com::sun::star::uno::RuntimeException)
148 {
149     return ::comphelper::findValue( getSupportedServiceNames(), _rServiceName, sal_True ).getLength() != 0;
150 }
151 
152 // --------------------------------------------------------------------------------
153 Any SAL_CALL OConnectionWrapper::queryInterface( const Type& _rType ) throw (RuntimeException)
154 {
155     Any aReturn = OConnection_BASE::queryInterface(_rType);
156     return aReturn.hasValue() ? aReturn : (m_xProxyConnection.is() ? m_xProxyConnection->queryAggregation(_rType) : aReturn);
157 }
158 // --------------------------------------------------------------------------------
159 Sequence< Type > SAL_CALL OConnectionWrapper::getTypes(  ) throw (::com::sun::star::uno::RuntimeException)
160 {
161     return ::comphelper::concatSequences(
162         OConnection_BASE::getTypes(),
163         m_xTypeProvider->getTypes()
164     );
165 }
166 // -----------------------------------------------------------------------------
167 // com::sun::star::lang::XUnoTunnel
168 sal_Int64 SAL_CALL OConnectionWrapper::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException)
169 {
170     if (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(),  rId.getConstArray(), 16 ) )
171         return reinterpret_cast< sal_Int64 >( this );
172 
173     if(m_xUnoTunnel.is())
174         return m_xUnoTunnel->getSomething(rId);
175     return 0;
176 }
177 
178 // -----------------------------------------------------------------------------
179 Sequence< sal_Int8 > OConnectionWrapper::getUnoTunnelImplementationId()
180 {
181     static ::cppu::OImplementationId * pId = 0;
182     if (! pId)
183     {
184         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
185         if (! pId)
186         {
187             static ::cppu::OImplementationId aId;
188             pId = &aId;
189         }
190     }
191     return pId->getImplementationId();
192 }
193 // -----------------------------------------------------------------------------
194 namespace
195 {
196     class TPropertyValueLessFunctor : public ::std::binary_function< ::com::sun::star::beans::PropertyValue,::com::sun::star::beans::PropertyValue,bool>
197     {
198     public:
199         TPropertyValueLessFunctor()
200         {}
201         bool operator() (const ::com::sun::star::beans::PropertyValue& lhs, const ::com::sun::star::beans::PropertyValue& rhs) const
202         {
203             return !!(lhs.Name.equalsIgnoreAsciiCase( rhs.Name ));
204         }
205     };
206 
207 }
208 
209 // -----------------------------------------------------------------------------
210 // creates a unique id out of the url and sequence of properties
211 void OConnectionWrapper::createUniqueId( const ::rtl::OUString& _rURL
212                     ,Sequence< PropertyValue >& _rInfo
213                     ,sal_uInt8* _pBuffer
214                     ,const ::rtl::OUString& _rUserName
215                     ,const ::rtl::OUString& _rPassword)
216 {
217     // first we create the digest we want to have
218     rtlDigest aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
219     rtlDigestError aError = rtl_digest_update(aDigest,_rURL.getStr(),_rURL.getLength()*sizeof(sal_Unicode));
220     if ( _rUserName.getLength() )
221         aError = rtl_digest_update(aDigest,_rUserName.getStr(),_rUserName.getLength()*sizeof(sal_Unicode));
222     if ( _rPassword.getLength() )
223         aError = rtl_digest_update(aDigest,_rPassword.getStr(),_rPassword.getLength()*sizeof(sal_Unicode));
224     // now we need to sort the properties
225     PropertyValue* pBegin = _rInfo.getArray();
226     PropertyValue* pEnd   = pBegin + _rInfo.getLength();
227     ::std::sort(pBegin,pEnd,TPropertyValueLessFunctor());
228 
229     pBegin = _rInfo.getArray();
230     pEnd   = pBegin + _rInfo.getLength();
231     for (; pBegin != pEnd; ++pBegin)
232     {
233         // we only include strings an integer values
234         ::rtl::OUString sValue;
235         if ( pBegin->Value >>= sValue )
236             ;
237         else
238         {
239             sal_Int32 nValue = 0;
240             if ( pBegin->Value >>= nValue )
241                 sValue = ::rtl::OUString::valueOf(nValue);
242             else
243             {
244                 Sequence< ::rtl::OUString> aSeq;
245                 if ( pBegin->Value >>= aSeq )
246                 {
247                     const ::rtl::OUString* pSBegin = aSeq.getConstArray();
248                     const ::rtl::OUString* pSEnd   = pSBegin + aSeq.getLength();
249                     for(;pSBegin != pSEnd;++pSBegin)
250                         aError = rtl_digest_update(aDigest,pSBegin->getStr(),pSBegin->getLength()*sizeof(sal_Unicode));
251                 }
252             }
253         }
254         if ( sValue.getLength() > 0 )
255         {
256             // we don't have to convert this into UTF8 because we don't store on a file system
257             aError = rtl_digest_update(aDigest,sValue.getStr(),sValue.getLength()*sizeof(sal_Unicode));
258         }
259     }
260 
261     aError = rtl_digest_get(aDigest,_pBuffer,RTL_DIGEST_LENGTH_SHA1);
262     // we have to destroy the digest
263     rtl_digest_destroy(aDigest);
264 }
265 // -----------------------------------------------------------------------------
266 
267 
268