Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/connectivity/source/commontools/ConnectionWrapper.cxx
Line
Count
Source
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 <connectivity/ConnectionWrapper.hxx>
21
#include <com/sun/star/beans/PropertyValue.hpp>
22
#include <com/sun/star/sdbc/XConnection.hpp>
23
#include <comphelper/uno3.hxx>
24
#include <comphelper/sequence.hxx>
25
#include <comphelper/servicehelper.hxx>
26
#include <comphelper/hash.hxx>
27
#include <cppuhelper/supportsservice.hxx>
28
#include <com/sun/star/reflection/ProxyFactory.hpp>
29
#include <algorithm>
30
31
using namespace connectivity;
32
33
using namespace com::sun::star::uno;
34
using namespace com::sun::star::lang;
35
using namespace com::sun::star::beans;
36
using namespace com::sun::star::sdbc;
37
using namespace ::com::sun::star::reflection;
38
39
OConnectionWrapper::OConnectionWrapper()
40
0
    : OConnection_BASE(m_aMutex)
41
0
{
42
43
0
}
44
45
void OConnectionWrapper::setDelegation(Reference< XAggregation >& _rxProxyConnection)
46
0
{
47
    // So far only called from constructors
48
0
    OSL_ENSURE(_rxProxyConnection.is(),"OConnectionWrapper: Connection must be valid!");
49
0
    osl_atomic_increment(&m_refCount);
50
0
    if (_rxProxyConnection.is())
51
0
    {
52
        // transfer the (one and only) real ref to the aggregate to our member
53
0
        m_xProxyConnection = _rxProxyConnection;
54
0
        _rxProxyConnection = nullptr;
55
0
        ::comphelper::query_aggregation(m_xProxyConnection,m_xConnection);
56
0
        m_xTypeProvider.set(m_xConnection,UNO_QUERY);
57
0
        m_xUnoTunnel.set(m_xConnection,UNO_QUERY);
58
0
        m_xServiceInfo.set(m_xConnection,UNO_QUERY);
59
60
        // set ourself as delegator
61
0
        Reference<XInterface> xIf = static_cast< XUnoTunnel* >( this );
62
0
        m_xProxyConnection->setDelegator( xIf );
63
64
0
    }
65
0
    osl_atomic_decrement(&m_refCount);
66
0
}
67
68
void OConnectionWrapper::setDelegation(const Reference< XConnection >& _xConnection
69
                                       ,const Reference< XComponentContext>& _rxContext)
70
0
{
71
    // So far only called from constructors
72
0
    OSL_ENSURE(_xConnection.is(),"OConnectionWrapper: Connection must be valid!");
73
0
    osl_atomic_increment(&m_refCount);
74
75
0
    m_xConnection = _xConnection;
76
0
    m_xTypeProvider.set(m_xConnection,UNO_QUERY);
77
0
    m_xUnoTunnel.set(m_xConnection,UNO_QUERY);
78
0
    m_xServiceInfo.set(m_xConnection,UNO_QUERY);
79
80
0
    Reference< XProxyFactory >  xProxyFactory = ProxyFactory::create( _rxContext );
81
0
    Reference< XAggregation > xConProxy = xProxyFactory->createProxy(_xConnection);
82
0
    if (xConProxy.is())
83
0
    {
84
        // transfer the (one and only) real ref to the aggregate to our member
85
0
        m_xProxyConnection = std::move(xConProxy);
86
87
        // set ourself as delegator
88
0
        Reference<XInterface> xIf = static_cast< XUnoTunnel* >( this );
89
0
        m_xProxyConnection->setDelegator( xIf );
90
91
0
    }
92
0
    osl_atomic_decrement(&m_refCount);
93
0
}
94
95
void OConnectionWrapper::disposing()
96
0
{
97
0
    osl::MutexGuard aGuard(m_aMutex);
98
0
    OConnection_BASE::disposing();
99
0
    m_xConnection.clear();
100
0
}
101
102
OConnectionWrapper::~OConnectionWrapper()
103
0
{
104
0
    if (m_xProxyConnection.is())
105
0
        m_xProxyConnection->setDelegator(nullptr);
106
0
}
107
108
// XServiceInfo
109
110
OUString SAL_CALL OConnectionWrapper::getImplementationName(  )
111
0
{
112
0
    return u"com.sun.star.sdbc.drivers.OConnectionWrapper"_ustr;
113
0
}
114
115
116
css::uno::Sequence< OUString > SAL_CALL OConnectionWrapper::getSupportedServiceNames(  )
117
0
{
118
0
    osl::MutexGuard aGuard(m_aMutex);
119
    // first collect the services which are supported by our aggregate
120
0
    Sequence< OUString > aSupported;
121
0
    if ( m_xServiceInfo.is() )
122
0
        aSupported = m_xServiceInfo->getSupportedServiceNames();
123
124
    // append our own service, if necessary
125
0
    OUString sConnectionService( u"com.sun.star.sdbc.Connection"_ustr );
126
0
    if ( ::comphelper::findValue( aSupported, sConnectionService ) == -1 )
127
0
    {
128
0
        sal_Int32 nLen = aSupported.getLength();
129
0
        aSupported.realloc( nLen + 1 );
130
0
        aSupported.getArray()[ nLen ] = sConnectionService;
131
0
    }
132
133
    // outta here
134
0
    return aSupported;
135
0
}
136
137
138
sal_Bool SAL_CALL OConnectionWrapper::supportsService( const OUString& _rServiceName )
139
0
{
140
0
    return cppu::supportsService(this, _rServiceName);
141
0
}
142
143
144
Any SAL_CALL OConnectionWrapper::queryInterface( const Type& _rType )
145
0
{
146
0
    osl::MutexGuard aGuard(m_aMutex);
147
0
    Any aReturn = OConnection_BASE::queryInterface(_rType);
148
0
    return aReturn.hasValue() ? aReturn : (m_xProxyConnection.is() ? m_xProxyConnection->queryAggregation(_rType) : aReturn);
149
0
}
150
151
Sequence< Type > SAL_CALL OConnectionWrapper::getTypes(  )
152
0
{
153
0
    osl::MutexGuard aGuard(m_aMutex);
154
0
    return ::comphelper::concatSequences(
155
0
        OConnection_BASE::getTypes(),
156
0
        m_xTypeProvider->getTypes()
157
0
    );
158
0
}
159
160
// css::lang::XUnoTunnel
161
sal_Int64 SAL_CALL OConnectionWrapper::getSomething( const Sequence< sal_Int8 >& rId )
162
0
{
163
0
    if (comphelper::isUnoTunnelId<OConnectionWrapper>(rId))
164
0
        return comphelper::getSomething_cast(this);
165
166
0
    osl::MutexGuard aGuard(m_aMutex);
167
0
    if(m_xUnoTunnel.is())
168
0
        return m_xUnoTunnel->getSomething(rId);
169
0
    return 0;
170
0
}
171
172
173
const Sequence< sal_Int8 > & OConnectionWrapper::getUnoTunnelId()
174
0
{
175
0
    static const comphelper::UnoIdInit implId;
176
0
    return implId.getSeq();
177
0
}
178
179
namespace
180
{
181
    class TPropertyValueLessFunctor
182
    {
183
    public:
184
        TPropertyValueLessFunctor()
185
0
        {}
186
        bool operator() (const css::beans::PropertyValue& lhs, const css::beans::PropertyValue& rhs) const
187
0
        {
188
0
            return lhs.Name.compareToIgnoreAsciiCase(rhs.Name) < 0;
189
0
        }
190
    };
191
192
}
193
194
195
// creates a unique id out of the url and sequence of properties
196
void OConnectionWrapper::createUniqueId( const OUString& _rURL
197
                    ,Sequence< PropertyValue >& _rInfo
198
                    ,sal_uInt8* _pBuffer
199
                    ,const OUString& _rUserName
200
                    ,const OUString& _rPassword)
201
0
{
202
    // first we create the digest we want to have
203
0
    ::comphelper::Hash sha1(::comphelper::HashType::SHA1);
204
0
    sha1.update(_rURL.getStr(), _rURL.getLength() * sizeof(sal_Unicode));
205
0
    if ( !_rUserName.isEmpty() )
206
0
        sha1.update(_rUserName.getStr(), _rUserName.getLength() * sizeof(sal_Unicode));
207
0
    if ( !_rPassword.isEmpty() )
208
0
        sha1.update(_rPassword.getStr(), _rPassword.getLength() * sizeof(sal_Unicode));
209
    // now we need to sort the properties
210
0
    auto [begin, end] = asNonConstRange(_rInfo);
211
0
    std::sort(begin,end,TPropertyValueLessFunctor());
212
213
0
    for (PropertyValue const& prop : _rInfo)
214
0
    {
215
        // we only include strings an integer values
216
0
        OUString sValue;
217
0
        if ( prop.Value >>= sValue )
218
0
            ;
219
0
        else
220
0
        {
221
0
            sal_Int32 nValue = 0;
222
0
            if ( prop.Value >>= nValue )
223
0
                sValue = OUString::number(nValue);
224
0
            else
225
0
            {
226
0
                Sequence< OUString> aSeq;
227
0
                if ( prop.Value >>= aSeq )
228
0
                {
229
0
                    for (OUString const& s : aSeq)
230
0
                        sha1.update(s.getStr(), s.getLength() * sizeof(sal_Unicode));
231
0
                }
232
0
            }
233
0
        }
234
0
        if ( !sValue.isEmpty() )
235
0
        {
236
            // we don't have to convert this into UTF8 because we don't store on a file system
237
0
            sha1.update(sValue.getStr(), sValue.getLength() * sizeof(sal_Unicode));
238
0
        }
239
0
    }
240
241
0
    std::vector<unsigned char> result(sha1.finalize());
242
0
    std::copy(result.begin(), result.end(), _pBuffer);
243
0
}
244
245
246
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */