1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
26 #include <com/sun/star/ucb/OpenMode.hpp>
27 #include <ucbhelper/contentidentifier.hxx>
28 #include <ucbhelper/providerhelper.hxx>
29 #include "webdavdatasupplier.hxx"
30 #include "webdavcontent.hxx"
31 #include "ContentProperties.hxx"
32 #include "DAVProperties.hxx"
33 #include "SerfUri.hxx"
34 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
35 #include <com/sun/star/ucb/ResultSetException.hpp>
36 #include <tools/diagnose_ex.h>
38 using namespace com::sun::star
;
39 using namespace http_dav_ucp
;
41 namespace http_dav_ucp
45 // struct ResultListEntry.
49 struct ResultListEntry
52 uno::Reference
< ucb::XContentIdentifier
> xId
;
53 uno::Reference
< ucb::XContent
> xContent
;
54 uno::Reference
< sdbc::XRow
> xRow
;
55 std::unique_ptr
<ContentProperties
> pData
;
57 explicit ResultListEntry( std::unique_ptr
<ContentProperties
> && pEntry
) : pData( std::move(pEntry
) ) {}
65 typedef std::vector
< ResultListEntry
* > ResultList
;
68 // struct DataSupplier_Impl.
71 struct DataSupplier_Impl
74 ResultList m_aResults
;
75 rtl::Reference
< Content
> m_xContent
;
76 uno::Reference
< uno::XComponentContext
> m_xContext
;
77 sal_Int32 m_nOpenMode
;
79 bool m_bThrowException
;
82 const uno::Reference
< uno::XComponentContext
>& rxContext
,
83 const rtl::Reference
< Content
>& rContent
,
85 : m_xContent( rContent
), m_xContext( rxContext
), m_nOpenMode( nOpenMode
),
86 m_bCountFinal( false ), m_bThrowException( false ) {}
91 DataSupplier_Impl::~DataSupplier_Impl()
93 for ( auto& rResultPtr
: m_aResults
)
102 // DataSupplier Implementation.
105 DataSupplier::DataSupplier(
106 const uno::Reference
< uno::XComponentContext
>& rxContext
,
107 const rtl::Reference
< Content
>& rContent
,
108 sal_Int32 nOpenMode
)
109 : m_pImpl(std::make_unique
<DataSupplier_Impl
>(rxContext
, rContent
, nOpenMode
))
115 DataSupplier::~DataSupplier()
120 OUString
DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex
)
122 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
124 if ( nIndex
< m_pImpl
->m_aResults
.size() )
126 OUString aId
= m_pImpl
->m_aResults
[ nIndex
]->aId
;
127 if ( aId
.getLength() )
134 if ( getResult( nIndex
) )
136 OUString aId
= m_pImpl
->m_xContent
->getResourceAccess().getURL();
138 const ContentProperties
& props
139 = *( m_pImpl
->m_aResults
[ nIndex
]->pData
);
141 if ( ( aId
.lastIndexOf( '/' ) + 1 ) != aId
.getLength() )
144 aId
+= props
.getEscapedTitle();
146 if ( props
.isTrailingSlash() )
149 m_pImpl
->m_aResults
[ nIndex
]->aId
= aId
;
157 uno::Reference
< ucb::XContentIdentifier
>
158 DataSupplier::queryContentIdentifier( sal_uInt32 nIndex
)
160 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
162 if ( nIndex
< m_pImpl
->m_aResults
.size() )
164 uno::Reference
< ucb::XContentIdentifier
> xId
165 = m_pImpl
->m_aResults
[ nIndex
]->xId
;
173 OUString aId
= queryContentIdentifierString( nIndex
);
174 if ( aId
.getLength() )
176 uno::Reference
< ucb::XContentIdentifier
> xId
177 = new ::ucbhelper::ContentIdentifier( aId
);
178 m_pImpl
->m_aResults
[ nIndex
]->xId
= xId
;
181 return uno::Reference
< ucb::XContentIdentifier
>();
186 uno::Reference
< ucb::XContent
>
187 DataSupplier::queryContent( sal_uInt32 nIndex
)
189 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
191 if ( nIndex
< m_pImpl
->m_aResults
.size() )
193 uno::Reference
< ucb::XContent
> xContent
194 = m_pImpl
->m_aResults
[ nIndex
]->xContent
;
202 uno::Reference
< ucb::XContentIdentifier
> xId
203 = queryContentIdentifier( nIndex
);
208 uno::Reference
< ucb::XContent
> xContent
209 = m_pImpl
->m_xContent
->getProvider()->queryContent( xId
);
210 m_pImpl
->m_aResults
[ nIndex
]->xContent
= xContent
;
214 catch ( ucb::IllegalIdentifierException
& )
218 return uno::Reference
< ucb::XContent
>();
223 bool DataSupplier::getResult( sal_uInt32 nIndex
)
225 osl::ClearableGuard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
227 if ( m_pImpl
->m_aResults
.size() > nIndex
)
229 // Result already present.
236 if ( m_pImpl
->m_aResults
.size() > nIndex
)
238 // Result already present.
248 sal_uInt32
DataSupplier::totalCount()
253 return m_pImpl
->m_aResults
.size();
258 sal_uInt32
DataSupplier::currentCount()
260 return m_pImpl
->m_aResults
.size();
265 bool DataSupplier::isCountFinal()
267 return m_pImpl
->m_bCountFinal
;
272 uno::Reference
< sdbc::XRow
> DataSupplier::queryPropertyValues(
275 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
277 if ( nIndex
< m_pImpl
->m_aResults
.size() )
279 uno::Reference
< sdbc::XRow
> xRow
= m_pImpl
->m_aResults
[ nIndex
]->xRow
;
287 if ( getResult( nIndex
) )
289 uno::Reference
< sdbc::XRow
> xRow
290 = Content::getPropertyValues(
292 getResultSet()->getProperties(),
293 *(m_pImpl
->m_aResults
[ nIndex
]->pData
),
294 rtl::Reference
< ::ucbhelper::ContentProviderImplHelper
>(
295 m_pImpl
->m_xContent
->getProvider().get() ),
296 queryContentIdentifierString( nIndex
) );
297 m_pImpl
->m_aResults
[ nIndex
]->xRow
= xRow
;
301 return uno::Reference
< sdbc::XRow
>();
306 void DataSupplier::releasePropertyValues( sal_uInt32 nIndex
)
308 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
310 if ( nIndex
< m_pImpl
->m_aResults
.size() )
311 m_pImpl
->m_aResults
[ nIndex
]->xRow
.clear();
316 void DataSupplier::close()
322 void DataSupplier::validate()
324 if ( m_pImpl
->m_bThrowException
)
325 throw ucb::ResultSetException();
328 bool DataSupplier::getData()
330 osl::ClearableGuard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
332 if ( !m_pImpl
->m_bCountFinal
)
334 std::vector
< OUString
> propertyNames
;
335 ContentProperties::UCBNamesToDAVNames(
336 getResultSet()->getProperties(), propertyNames
);
338 // Append "resourcetype", if not already present. It's value is
339 // needed to get a valid ContentProperties::pIsFolder value, which
340 // is needed for OpenMode handling.
342 bool isNoResourceType
= std::none_of(propertyNames
.begin(), propertyNames
.end(),
343 [](const OUString
& rPropName
) { return rPropName
.equals(DAVProperties::RESOURCETYPE
); });
345 if ( isNoResourceType
)
346 propertyNames
.push_back( DAVProperties::RESOURCETYPE
);
348 std::vector
< DAVResource
> resources
;
351 // propfind depth 1, get property values for parent AND for each
353 m_pImpl
->m_xContent
->getResourceAccess()
357 getResultSet()->getEnvironment() );
359 catch ( DAVException
& )
361 TOOLS_WARN_EXCEPTION( "ucb.ucp.webdav", "PROPFIND : DAVException" );
362 m_pImpl
->m_bThrowException
= true;
365 if ( !m_pImpl
->m_bThrowException
)
370 m_pImpl
->m_xContent
->getResourceAccess().getURL() );
371 OUString aPath
= aURI
.GetPath();
373 if ( aPath
.endsWith("/") )
374 aPath
= aPath
.copy( 0, aPath
.getLength() - 1 );
376 aPath
= SerfUri::unescape( aPath
);
377 bool bFoundParent
= false;
379 for ( size_t n
= 0; n
< resources
.size(); ++n
)
381 const DAVResource
& rRes
= resources
[ n
];
383 // Filter parent, which is contained somewhere(!) in
389 SerfUri
aCurrURI( rRes
.uri
);
390 OUString aCurrPath
= aCurrURI
.GetPath();
391 if ( aCurrPath
.endsWith("/") )
395 aCurrPath
.getLength() - 1 );
397 aCurrPath
= SerfUri::unescape( aCurrPath
);
398 if ( aPath
== aCurrPath
)
404 catch ( DAVException
const & )
406 // do nothing, ignore error. continue.
410 std::unique_ptr
<ContentProperties
> pContentProperties
411 = std::make_unique
<ContentProperties
>( rRes
);
413 // Check resource against open mode.
414 switch ( m_pImpl
->m_nOpenMode
)
416 case ucb::OpenMode::FOLDERS
:
418 bool bFolder
= false;
420 const uno::Any
& rValue
421 = pContentProperties
->getValue( "IsFolder" );
430 case ucb::OpenMode::DOCUMENTS
:
432 bool bDocument
= false;
434 const uno::Any
& rValue
435 = pContentProperties
->getValue( "IsDocument" );
436 rValue
>>= bDocument
;
444 case ucb::OpenMode::ALL
:
449 m_pImpl
->m_aResults
.push_back(
450 new ResultListEntry( std::move(pContentProperties
) ) );
453 catch ( DAVException
const & )
458 m_pImpl
->m_bCountFinal
= true;
460 // Callback possible, because listeners may be informed!
462 getResultSet()->rowCountFinal();
464 return !m_pImpl
->m_bThrowException
;
467 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */