Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/dataprovider/dataprovider.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
10
#include <dataprovider.hxx>
11
#include <com/sun/star/ucb/XSimpleFileAccess3.hpp>
12
#include <com/sun/star/ucb/SimpleFileAccess.hpp>
13
#include <com/sun/star/io/XInputStream.hpp>
14
#include <o3tl/string_view.hxx>
15
#include <rtl/strbuf.hxx>
16
#include <sal/log.hxx>
17
#include <unotools/charclass.hxx>
18
#include <tools/stream.hxx>
19
#include <comphelper/processfactory.hxx>
20
21
#include "htmldataprovider.hxx"
22
#include "xmldataprovider.hxx"
23
#include "sqldataprovider.hxx"
24
#include <datamapper.hxx>
25
#include <dbdata.hxx>
26
#include <docsh.hxx>
27
#include <utility>
28
29
using namespace com::sun::star;
30
31
namespace sc {
32
33
std::unique_ptr<SvStream> DataProvider::FetchStreamFromURL(const OUString& rURL, OStringBuffer& rBuffer)
34
0
{
35
0
    try
36
0
    {
37
0
        uno::Reference< ucb::XSimpleFileAccess3 > xFileAccess = ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() );
38
39
0
        uno::Reference< io::XInputStream > xStream = xFileAccess->openFileRead( rURL );
40
41
0
        const sal_Int32 BUF_LEN = 8000;
42
0
        uno::Sequence< sal_Int8 > buffer( BUF_LEN );
43
44
0
        sal_Int32 nRead = 0;
45
0
        while ( ( nRead = xStream->readBytes( buffer, BUF_LEN ) ) == BUF_LEN )
46
0
        {
47
0
            rBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead );
48
0
        }
49
50
0
        if ( nRead > 0 )
51
0
        {
52
0
            rBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead );
53
0
        }
54
55
0
        xStream->closeInput();
56
57
0
        SvStream* pStream = new SvMemoryStream(const_cast<char*>(rBuffer.getStr()), rBuffer.getLength(), StreamMode::READ);
58
0
        return std::unique_ptr<SvStream>(pStream);
59
0
    }
60
0
    catch(...)
61
0
    {
62
0
        rBuffer.setLength(0);
63
0
        return nullptr;
64
0
    }
65
0
}
66
67
ExternalDataSource::ExternalDataSource(OUString aURL,
68
        OUString aProvider, ScDocument* pDoc)
69
0
    : maURL(std::move(aURL))
70
0
    , maProvider(std::move(aProvider))
71
0
    , mpDoc(pDoc)
72
0
{
73
0
}
74
75
void ExternalDataSource::setID(const OUString& rID)
76
0
{
77
0
    maID = rID;
78
0
}
79
80
void ExternalDataSource::setXMLImportParam(const ScOrcusImportXMLParam& rParam)
81
0
{
82
0
    maParam = rParam;
83
0
}
84
85
86
87
void ExternalDataSource::setURL(const OUString& rURL)
88
0
{
89
0
    maURL = rURL;
90
0
}
91
92
void ExternalDataSource::setProvider(const OUString& rProvider)
93
0
{
94
0
    maProvider = rProvider;
95
0
    mpDataProvider.reset();
96
0
}
97
98
const OUString& ExternalDataSource::getURL() const
99
0
{
100
0
    return maURL;
101
0
}
102
103
const OUString& ExternalDataSource::getProvider() const
104
0
{
105
0
    return maProvider;
106
0
}
107
108
const OUString& ExternalDataSource::getID() const
109
0
{
110
0
    return maID;
111
0
}
112
113
const ScOrcusImportXMLParam& ExternalDataSource::getXMLImportParam() const
114
0
{
115
0
    return maParam;
116
0
}
117
118
OUString ExternalDataSource::getDBName() const
119
0
{
120
0
    if (mpDBDataManager)
121
0
    {
122
0
        ScDBData* pDBData = mpDBDataManager->getDBData();
123
0
        if (pDBData)
124
0
            return pDBData->GetName();
125
0
    }
126
0
    return OUString();
127
0
}
128
129
void ExternalDataSource::setDBData(const OUString& rDBName)
130
0
{
131
0
    if (!mpDBDataManager)
132
0
    {
133
0
        mpDBDataManager = std::make_shared<ScDBDataManager>(rDBName, mpDoc);
134
0
    }
135
0
    else
136
0
    {
137
0
        mpDBDataManager->SetDatabase(rDBName);
138
0
    }
139
0
}
140
141
double ExternalDataSource::getUpdateFrequency()
142
0
{
143
0
    return 0;
144
0
}
145
146
ScDBDataManager* ExternalDataSource::getDBManager()
147
0
{
148
0
    return mpDBDataManager.get();
149
0
}
150
151
void ExternalDataSource::refresh(ScDocument* pDoc, bool bDeterministic)
152
0
{
153
    // no DB data available
154
0
    if (!mpDBDataManager)
155
0
        return;
156
157
    // tdf#169541 An existing mpDataProvider might have a corrupted backreference to `this`.
158
    // Thus create a new one in any case.
159
0
    mpDataProvider = DataProviderFactory::getDataProvider(pDoc, *this);
160
161
    // if we have not been able to create one, we can not refresh the data
162
0
    if (!mpDataProvider)
163
0
        return;
164
165
0
    if (bDeterministic)
166
0
        mpDataProvider->setDeterministic();
167
168
0
    mpDataProvider->Import();
169
0
}
170
171
void ExternalDataSource::AddDataTransformation(
172
    const std::shared_ptr<sc::DataTransformation>& mpDataTransformation)
173
0
{
174
0
    maDataTransformations.push_back(mpDataTransformation);
175
0
}
176
177
const std::vector<std::shared_ptr<sc::DataTransformation>>& ExternalDataSource::getDataTransformation() const
178
0
{
179
0
    return maDataTransformations;
180
0
}
181
182
ExternalDataMapper::ExternalDataMapper(ScDocument& /*rDoc*/)
183
    //mrDoc(rDoc)
184
0
{
185
0
}
186
187
ExternalDataMapper::~ExternalDataMapper()
188
0
{
189
0
}
190
191
void ExternalDataMapper::insertDataSource(const sc::ExternalDataSource& rSource)
192
0
{
193
0
    maDataSources.push_back(rSource);
194
0
}
195
196
const std::vector<sc::ExternalDataSource>& ExternalDataMapper::getDataSources() const
197
0
{
198
0
    return maDataSources;
199
0
}
200
201
std::vector<sc::ExternalDataSource>& ExternalDataMapper::getDataSources()
202
0
{
203
0
    return maDataSources;
204
0
}
205
206
DataProvider::DataProvider(sc::ExternalDataSource& rDataSource):
207
0
    mbDeterministic(false),
208
0
    mrDataSource(rDataSource)
209
0
{
210
0
}
211
212
void DataProvider::setDeterministic()
213
0
{
214
0
    mbDeterministic = true;
215
0
}
216
217
DataProvider::~DataProvider()
218
0
{
219
0
}
220
221
void ScDBDataManager::WriteToDoc(ScDocument& rDoc)
222
0
{
223
    // first apply all data transformations
224
225
0
    bool bShrunk = false;
226
0
    SCCOL nStartCol = 0;
227
0
    SCROW nStartRow = 0;
228
0
    SCCOL nEndCol = rDoc.MaxCol();
229
0
    SCROW nEndRow = rDoc.MaxRow();
230
0
    rDoc.ShrinkToUsedDataArea(bShrunk, 0, nStartCol, nStartRow, nEndCol, nEndRow, false, true, true);
231
0
    ScRange aClipRange(nStartCol, nStartRow, 0, nEndCol, nEndRow, 0);
232
0
    rDoc.SetClipArea(aClipRange);
233
234
0
    ScRange aDestRange;
235
0
    getDBData()->GetArea(aDestRange);
236
0
    SCCOL nColSize = std::min<SCCOL>(aDestRange.aEnd.Col() - aDestRange.aStart.Col(), nEndCol);
237
0
    aDestRange.aEnd.SetCol(aDestRange.aStart.Col() + nColSize);
238
239
0
    SCROW nRowSize = std::min<SCROW>(aDestRange.aEnd.Row() - aDestRange.aStart.Row(), nEndRow);
240
0
    aDestRange.aEnd.SetRow(aDestRange.aStart.Row() + nRowSize);
241
242
0
    ScMarkData aMark(mpDoc->GetSheetLimits());
243
0
    aMark.SelectTable(aDestRange.aStart.Tab(), true);
244
0
    mpDoc->CopyFromClip(aDestRange, aMark, InsertDeleteFlags::CONTENTS, nullptr, &rDoc);
245
0
    ScDocShell* pDocShell = mpDoc->GetDocumentShell();
246
0
    if (pDocShell)
247
0
        pDocShell->PostPaint(aDestRange, PaintPartFlags::All);
248
0
}
249
250
ScDBDataManager::ScDBDataManager(OUString aDBName, ScDocument* pDoc):
251
0
    maDBName(std::move(aDBName)),
252
0
    mpDoc(pDoc)
253
0
{
254
0
}
255
256
ScDBDataManager::~ScDBDataManager()
257
0
{
258
0
}
259
260
void ScDBDataManager::SetDatabase(const OUString& rDBName)
261
0
{
262
0
    maDBName = rDBName;
263
0
}
264
265
ScDBData* ScDBDataManager::getDBData()
266
0
{
267
0
    ScDBData* pDBData = mpDoc->GetDBCollection()->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(maDBName));
268
0
    return pDBData;
269
0
}
270
271
bool DataProviderFactory::isInternalDataProvider(std::u16string_view rProvider)
272
0
{
273
0
    return o3tl::starts_with(rProvider, u"org.libreoffice.calc");
274
0
}
275
276
std::shared_ptr<DataProvider> DataProviderFactory::getDataProvider(ScDocument* pDoc,
277
        sc::ExternalDataSource& rDataSource)
278
0
{
279
0
    const OUString& rDataProvider = rDataSource.getProvider();
280
0
    bool bInternal = DataProviderFactory::isInternalDataProvider(rDataProvider);
281
0
    if (bInternal)
282
0
    {
283
0
        if (rDataProvider == "org.libreoffice.calc.csv")
284
0
            return std::make_shared<CSVDataProvider>(pDoc, rDataSource);
285
0
        else if (rDataProvider == "org.libreoffice.calc.html")
286
0
            return std::make_shared<HTMLDataProvider>(pDoc, rDataSource);
287
0
        else if (rDataProvider == "org.libreoffice.calc.xml")
288
0
            return std::make_shared<XMLDataProvider>(pDoc, rDataSource);
289
0
        else if (rDataProvider == "org.libreoffice.calc.sql")
290
0
            return std::make_shared<SQLDataProvider>(pDoc, rDataSource);
291
0
    }
292
0
    else
293
0
    {
294
0
        SAL_WARN("sc", "no external data provider supported yet");
295
0
        return std::shared_ptr<DataProvider>();
296
0
    }
297
298
0
    return std::shared_ptr<DataProvider>();
299
0
}
300
301
}
302
303
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */