1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 /**************************************************************************
32 **************************************************************************
34 *************************************************************************/
36 #include <sal/log.hxx>
37 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
38 #include <com/sun/star/ucb/OpenMode.hpp>
39 #include <com/sun/star/ucb/ResultSetException.hpp>
40 #include <ucbhelper/contentidentifier.hxx>
41 #include <ucbhelper/providerhelper.hxx>
42 #include <tools/diagnose_ex.h>
45 #include "webdavdatasupplier.hxx"
46 #include "webdavcontent.hxx"
47 #include "ContentProperties.hxx"
48 #include "NeonUri.hxx"
50 using namespace com::sun::star
;
51 using namespace webdav_ucp
;
57 // struct ResultListEntry.
61 struct ResultListEntry
64 uno::Reference
< ucb::XContentIdentifier
> xId
;
65 uno::Reference
< ucb::XContent
> xContent
;
66 uno::Reference
< sdbc::XRow
> xRow
;
67 std::shared_ptr
<ContentProperties
> const pData
;
69 explicit ResultListEntry(std::shared_ptr
<ContentProperties
> const& pEntry
)
79 typedef std::vector
<std::unique_ptr
<ResultListEntry
>> ResultList
;
82 // struct DataSupplier_Impl.
85 struct DataSupplier_Impl
89 rtl::Reference
< Content
> m_xContent
;
90 uno::Reference
< uno::XComponentContext
> m_xContext
;
91 sal_Int32 m_nOpenMode
;
93 bool m_bThrowException
;
96 const uno::Reference
< uno::XComponentContext
>& rxContext
,
97 const rtl::Reference
< Content
>& rContent
,
99 : m_xContent( rContent
), m_xContext( rxContext
), m_nOpenMode( nOpenMode
),
100 m_bCountFinal( false ), m_bThrowException( false ) {}
106 // DataSupplier Implementation.
109 DataSupplier::DataSupplier(
110 const uno::Reference
< uno::XComponentContext
>& rxContext
,
111 const rtl::Reference
< Content
>& rContent
,
112 sal_Int32 nOpenMode
)
113 : m_pImpl( new DataSupplier_Impl( rxContext
, rContent
, nOpenMode
) )
119 DataSupplier::~DataSupplier()
125 OUString
DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex
)
127 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
129 if (nIndex
< m_pImpl
->m_Results
.size())
131 OUString aId
= m_pImpl
->m_Results
[ nIndex
]->aId
;
132 if ( !aId
.isEmpty() )
139 if ( getResult( nIndex
) )
141 OUString aId
= m_pImpl
->m_xContent
->getResourceAccess().getURL();
143 const ContentProperties
& props(*(m_pImpl
->m_Results
[ nIndex
]->pData
));
145 if ( ( aId
.lastIndexOf( '/' ) + 1 ) != aId
.getLength() )
148 aId
+= props
.getEscapedTitle();
150 if ( props
.isTrailingSlash() )
153 m_pImpl
->m_Results
[ nIndex
]->aId
= aId
;
161 uno::Reference
< ucb::XContentIdentifier
>
162 DataSupplier::queryContentIdentifier( sal_uInt32 nIndex
)
164 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
166 if (nIndex
< m_pImpl
->m_Results
.size())
168 uno::Reference
< ucb::XContentIdentifier
> xId
169 = m_pImpl
->m_Results
[ nIndex
]->xId
;
177 OUString aId
= queryContentIdentifierString( nIndex
);
178 if ( !aId
.isEmpty() )
180 uno::Reference
< ucb::XContentIdentifier
> xId
181 = new ::ucbhelper::ContentIdentifier( aId
);
182 m_pImpl
->m_Results
[ nIndex
]->xId
= xId
;
185 return uno::Reference
< ucb::XContentIdentifier
>();
190 uno::Reference
< ucb::XContent
>
191 DataSupplier::queryContent( sal_uInt32 nIndex
)
193 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
195 if (nIndex
< m_pImpl
->m_Results
.size())
197 uno::Reference
< ucb::XContent
> xContent
198 = m_pImpl
->m_Results
[ nIndex
]->xContent
;
206 uno::Reference
< ucb::XContentIdentifier
> xId
207 = queryContentIdentifier( nIndex
);
212 uno::Reference
< ucb::XContent
> xContent
213 = m_pImpl
->m_xContent
->getProvider()->queryContent( xId
);
214 m_pImpl
->m_Results
[ nIndex
]->xContent
= xContent
;
218 catch ( ucb::IllegalIdentifierException
& )
222 return uno::Reference
< ucb::XContent
>();
227 bool DataSupplier::getResult( sal_uInt32 nIndex
)
229 osl::ClearableGuard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
231 if (nIndex
< m_pImpl
->m_Results
.size())
233 // Result already present.
240 if (nIndex
< m_pImpl
->m_Results
.size())
242 // Result already present.
252 sal_uInt32
DataSupplier::totalCount()
257 return m_pImpl
->m_Results
.size();
262 sal_uInt32
DataSupplier::currentCount()
264 return m_pImpl
->m_Results
.size();
269 bool DataSupplier::isCountFinal()
271 return m_pImpl
->m_bCountFinal
;
276 uno::Reference
< sdbc::XRow
> DataSupplier::queryPropertyValues(
279 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
281 if (nIndex
< m_pImpl
->m_Results
.size())
283 uno::Reference
< sdbc::XRow
> xRow
= m_pImpl
->m_Results
[ nIndex
]->xRow
;
291 if ( getResult( nIndex
) )
293 uno::Reference
< sdbc::XRow
> xRow
294 = Content::getPropertyValues(
296 getResultSet()->getProperties(),
297 *(m_pImpl
->m_Results
[ nIndex
]->pData
),
298 m_pImpl
->m_xContent
->getProvider(),
299 queryContentIdentifierString( nIndex
) );
300 m_pImpl
->m_Results
[ nIndex
]->xRow
= xRow
;
304 return uno::Reference
< sdbc::XRow
>();
309 void DataSupplier::releasePropertyValues( sal_uInt32 nIndex
)
311 osl::Guard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
313 if (nIndex
< m_pImpl
->m_Results
.size())
314 m_pImpl
->m_Results
[ nIndex
]->xRow
.clear();
319 void DataSupplier::close()
325 void DataSupplier::validate()
327 if ( m_pImpl
->m_bThrowException
)
328 throw ucb::ResultSetException();
332 bool DataSupplier::getData()
334 osl::ClearableGuard
< osl::Mutex
> aGuard( m_pImpl
->m_aMutex
);
336 if ( !m_pImpl
->m_bCountFinal
)
338 std::vector
< OUString
> propertyNames
;
339 ContentProperties::UCBNamesToDAVNames(
340 getResultSet()->getProperties(), propertyNames
);
342 // Append "resourcetype", if not already present. It's value is
343 // needed to get a valid ContentProperties::pIsFolder value, which
344 // is needed for OpenMode handling.
346 bool isNoResourceType
= std::none_of(propertyNames
.begin(), propertyNames
.end(),
347 [](const OUString
& rName
) { return rName
== DAVProperties::RESOURCETYPE
; });
349 if ( isNoResourceType
)
350 propertyNames
.push_back( DAVProperties::RESOURCETYPE
);
352 std::vector
< DAVResource
> resources
;
355 // propfind depth 1, get property values for parent AND for each
357 m_pImpl
->m_xContent
->getResourceAccess()
361 getResultSet()->getEnvironment() );
362 #if defined SAL_LOG_INFO
364 //print the resource for every URI returned
365 for ( const auto& rResource
: resources
)
367 NeonUri
aCurrURI( rResource
.uri
);
368 OUString aCurrPath
= aCurrURI
.GetPath();
369 aCurrPath
= NeonUri::unescape( aCurrPath
);
370 SAL_INFO( "ucb.ucp.webdav", "getData() - resource URL: <" << rResource
.uri
<< ">, unescaped to: <" << aCurrPath
<< "> )" );
371 for ( const auto& rProp
: rResource
.properties
)
373 SAL_INFO( "ucb.ucp.webdav", "PROPFIND - property name: " << rProp
.Name
);
379 catch ( DAVException
& )
381 TOOLS_WARN_EXCEPTION( "ucb.ucp.webdav", "Running PROPFIND: DAVException" );
382 m_pImpl
->m_bThrowException
= true;
385 if ( !m_pImpl
->m_bThrowException
)
390 m_pImpl
->m_xContent
->getResourceAccess().getURL() );
391 OUString aPath
= aURI
.GetPath();
393 if ( aPath
.endsWith("/") )
394 aPath
= aPath
.copy( 0, aPath
.getLength() - 1 );
396 aPath
= NeonUri::unescape( aPath
);
397 bool bFoundParent
= false;
399 for (DAVResource
& rRes
: resources
)
401 // Filter parent, which is contained somewhere(!) in
407 NeonUri
aCurrURI( rRes
.uri
);
408 OUString aCurrPath
= aCurrURI
.GetPath();
409 if ( aCurrPath
.endsWith("/") )
413 aCurrPath
.getLength() - 1 );
415 aCurrPath
= NeonUri::unescape( aCurrPath
);
416 if ( aPath
== aCurrPath
)
422 catch ( DAVException
const & )
424 // do nothing, ignore error. continue.
428 std::shared_ptr
<ContentProperties
> const
429 pContentProperties
= std::make_shared
<ContentProperties
>(rRes
);
431 // Check resource against open mode.
432 switch ( m_pImpl
->m_nOpenMode
)
434 case ucb::OpenMode::FOLDERS
:
436 bool bFolder
= false;
438 const uno::Any
& rValue
439 = pContentProperties
->getValue(
449 case ucb::OpenMode::DOCUMENTS
:
451 bool bDocument
= false;
453 const uno::Any
& rValue
454 = pContentProperties
->getValue(
456 rValue
>>= bDocument
;
464 case ucb::OpenMode::ALL
:
469 m_pImpl
->m_Results
.push_back(
470 std::make_unique
<ResultListEntry
>(pContentProperties
));
473 catch ( DAVException
const & )
478 m_pImpl
->m_bCountFinal
= true;
480 // Callback possible, because listeners may be informed!
482 getResultSet()->rowCountFinal();
484 return !m_pImpl
->m_bThrowException
;
487 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */