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