LibreOffice Module ucb (master)  1
webdavdatasupplier.cxx
Go to the documentation of this file.
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 <sal/config.h>
21 #include <sal/log.hxx>
22 
23 #include <memory>
24 #include <utility>
25 
26 #include <com/sun/star/ucb/OpenMode.hpp>
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 
37 using namespace com::sun::star;
38 using namespace http_dav_ucp;
39 
40 namespace http_dav_ucp
41 {
42 
43 
44 // struct ResultListEntry.
45 
46 
48 {
49  OUString aId;
50  uno::Reference< ucb::XContentIdentifier > xId;
51  uno::Reference< ucb::XContent > xContent;
52  uno::Reference< sdbc::XRow > xRow;
53  std::unique_ptr<ContentProperties> pData;
54 
55  explicit ResultListEntry( std::unique_ptr<ContentProperties> && pEntry ) : pData( std::move(pEntry) ) {}
56 };
57 
58 
59 // ResultList.
60 
61 
62 typedef std::vector< ResultListEntry* > ResultList;
63 
64 
65 // struct DataSupplier_Impl.
66 
67 
69 {
70  osl::Mutex m_aMutex;
71  ResultList m_aResults;
73  uno::Reference< uno::XComponentContext > m_xContext;
74  sal_Int32 m_nOpenMode;
77 
79  const uno::Reference< uno::XComponentContext >& rxContext,
80  const rtl::Reference< Content >& rContent,
81  sal_Int32 nOpenMode )
82  : m_xContent( rContent ), m_xContext( rxContext ), m_nOpenMode( nOpenMode ),
83  m_bCountFinal( false ), m_bThrowException( false ) {}
85 };
86 
87 
88 DataSupplier_Impl::~DataSupplier_Impl()
89 {
90  for ( auto& rResultPtr : m_aResults )
91  {
92  delete rResultPtr;
93  }
94 }
95 
96 }
97 
98 
99 // DataSupplier Implementation.
100 
101 
102 DataSupplier::DataSupplier(
103  const uno::Reference< uno::XComponentContext >& rxContext,
104  const rtl::Reference< Content >& rContent,
105  sal_Int32 nOpenMode )
106 : m_pImpl(std::make_unique<DataSupplier_Impl>(rxContext, rContent, nOpenMode))
107 {
108 }
109 
110 
111 // virtual
113 {}
114 
115 
116 // virtual
117 OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
118 {
119  osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
120 
121  if ( nIndex < m_pImpl->m_aResults.size() )
122  {
123  OUString aId = m_pImpl->m_aResults[ nIndex ]->aId;
124  if ( aId.getLength() )
125  {
126  // Already cached.
127  return aId;
128  }
129  }
130 
131  if ( getResult( nIndex ) )
132  {
133  OUString aId = m_pImpl->m_xContent->getResourceAccess().getURL();
134 
135  const ContentProperties& props
136  = *( m_pImpl->m_aResults[ nIndex ]->pData );
137 
138  if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() )
139  aId += "/";
140 
141  aId += props.getEscapedTitle();
142 
143  if ( props.isTrailingSlash() )
144  aId += "/";
145 
146  m_pImpl->m_aResults[ nIndex ]->aId = aId;
147  return aId;
148  }
149  return OUString();
150 }
151 
152 
153 // virtual
154 uno::Reference< ucb::XContentIdentifier >
156 {
157  osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
158 
159  if ( nIndex < m_pImpl->m_aResults.size() )
160  {
161  uno::Reference< ucb::XContentIdentifier > xId
162  = m_pImpl->m_aResults[ nIndex ]->xId;
163  if ( xId.is() )
164  {
165  // Already cached.
166  return xId;
167  }
168  }
169 
170  OUString aId = queryContentIdentifierString( nIndex );
171  if ( aId.getLength() )
172  {
173  uno::Reference< ucb::XContentIdentifier > xId
174  = new ::ucbhelper::ContentIdentifier( aId );
175  m_pImpl->m_aResults[ nIndex ]->xId = xId;
176  return xId;
177  }
178  return uno::Reference< ucb::XContentIdentifier >();
179 }
180 
181 
182 // virtual
183 uno::Reference< ucb::XContent >
184 DataSupplier::queryContent( sal_uInt32 nIndex )
185 {
186  osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
187 
188  if ( nIndex < m_pImpl->m_aResults.size() )
189  {
190  uno::Reference< ucb::XContent > xContent
191  = m_pImpl->m_aResults[ nIndex ]->xContent;
192  if ( xContent.is() )
193  {
194  // Already cached.
195  return xContent;
196  }
197  }
198 
199  uno::Reference< ucb::XContentIdentifier > xId
200  = queryContentIdentifier( nIndex );
201  if ( xId.is() )
202  {
203  try
204  {
205  uno::Reference< ucb::XContent > xContent
206  = m_pImpl->m_xContent->getProvider()->queryContent( xId );
207  m_pImpl->m_aResults[ nIndex ]->xContent = xContent;
208  return xContent;
209 
210  }
211  catch ( ucb::IllegalIdentifierException& )
212  {
213  }
214  }
215  return uno::Reference< ucb::XContent >();
216 }
217 
218 
219 // virtual
220 bool DataSupplier::getResult( sal_uInt32 nIndex )
221 {
222  osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
223 
224  if ( m_pImpl->m_aResults.size() > nIndex )
225  {
226  // Result already present.
227  return true;
228  }
229 
230  // Obtain values...
231  if ( getData() )
232  {
233  if ( m_pImpl->m_aResults.size() > nIndex )
234  {
235  // Result already present.
236  return true;
237  }
238  }
239 
240  return false;
241 }
242 
243 
244 // virtual
246 {
247  // Obtain values...
248  getData();
249 
250  return m_pImpl->m_aResults.size();
251 }
252 
253 
254 // virtual
256 {
257  return m_pImpl->m_aResults.size();
258 }
259 
260 
261 // virtual
263 {
264  return m_pImpl->m_bCountFinal;
265 }
266 
267 
268 // virtual
269 uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues(
270  sal_uInt32 nIndex )
271 {
272  osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
273 
274  if ( nIndex < m_pImpl->m_aResults.size() )
275  {
276  uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow;
277  if ( xRow.is() )
278  {
279  // Already cached.
280  return xRow;
281  }
282  }
283 
284  if ( getResult( nIndex ) )
285  {
286  uno::Reference< sdbc::XRow > xRow
288  m_pImpl->m_xContext,
289  getResultSet()->getProperties(),
290  *(m_pImpl->m_aResults[ nIndex ]->pData),
292  m_pImpl->m_xContent->getProvider().get() ),
293  queryContentIdentifierString( nIndex ) );
294  m_pImpl->m_aResults[ nIndex ]->xRow = xRow;
295  return xRow;
296  }
297 
298  return uno::Reference< sdbc::XRow >();
299 }
300 
301 
302 // virtual
303 void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
304 {
305  osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
306 
307  if ( nIndex < m_pImpl->m_aResults.size() )
308  m_pImpl->m_aResults[ nIndex ]->xRow.clear();
309 }
310 
311 
312 // virtual
314 {
315 }
316 
317 
318 // virtual
320 {
321  if ( m_pImpl->m_bThrowException )
322  throw ucb::ResultSetException();
323 }
324 
326 {
327  osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
328 
329  if ( !m_pImpl->m_bCountFinal )
330  {
331  std::vector< OUString > propertyNames;
333  getResultSet()->getProperties(), propertyNames );
334 
335  // Append "resourcetype", if not already present. It's value is
336  // needed to get a valid ContentProperties::pIsFolder value, which
337  // is needed for OpenMode handling.
338 
339  bool isNoResourceType = std::none_of(propertyNames.begin(), propertyNames.end(),
340  [](const OUString& rPropName) { return rPropName.equals(DAVProperties::RESOURCETYPE); });
341 
342  if ( isNoResourceType )
343  propertyNames.push_back( DAVProperties::RESOURCETYPE );
344 
345  std::vector< DAVResource > resources;
346  try
347  {
348  // propfind depth 1, get property values for parent AND for each
349  // child
350  m_pImpl->m_xContent->getResourceAccess()
351  .PROPFIND( DAVONE,
352  propertyNames,
353  resources,
355  }
356  catch ( DAVException & )
357  {
358  SAL_WARN( "ucb.ucp.webdav", "PROPFIND : DAVException" );
359  m_pImpl->m_bThrowException = true;
360  }
361 
362  if ( !m_pImpl->m_bThrowException )
363  {
364  try
365  {
366  SerfUri aURI(
367  m_pImpl->m_xContent->getResourceAccess().getURL() );
368  OUString aPath = aURI.GetPath();
369 
370  if ( aPath.endsWith("/") )
371  aPath = aPath.copy( 0, aPath.getLength() - 1 );
372 
373  aPath = SerfUri::unescape( aPath );
374  bool bFoundParent = false;
375 
376  for ( size_t n = 0; n < resources.size(); ++n )
377  {
378  const DAVResource & rRes = resources[ n ];
379 
380  // Filter parent, which is contained somewhere(!) in
381  // the vector.
382  if ( !bFoundParent )
383  {
384  try
385  {
386  SerfUri aCurrURI( rRes.uri );
387  OUString aCurrPath = aCurrURI.GetPath();
388  if ( aCurrPath.endsWith("/") )
389  aCurrPath
390  = aCurrPath.copy(
391  0,
392  aCurrPath.getLength() - 1 );
393 
394  aCurrPath = SerfUri::unescape( aCurrPath );
395  if ( aPath == aCurrPath )
396  {
397  bFoundParent = true;
398  continue;
399  }
400  }
401  catch ( DAVException const & )
402  {
403  // do nothing, ignore error. continue.
404  }
405  }
406 
407  std::unique_ptr<ContentProperties> pContentProperties
408  = std::make_unique<ContentProperties>( rRes );
409 
410  // Check resource against open mode.
411  switch ( m_pImpl->m_nOpenMode )
412  {
413  case ucb::OpenMode::FOLDERS:
414  {
415  bool bFolder = false;
416 
417  const uno::Any & rValue
418  = pContentProperties->getValue( "IsFolder" );
419  rValue >>= bFolder;
420 
421  if ( !bFolder )
422  continue;
423 
424  break;
425  }
426 
427  case ucb::OpenMode::DOCUMENTS:
428  {
429  bool bDocument = false;
430 
431  const uno::Any & rValue
432  = pContentProperties->getValue( "IsDocument" );
433  rValue >>= bDocument;
434 
435  if ( !bDocument )
436  continue;
437 
438  break;
439  }
440 
441  case ucb::OpenMode::ALL:
442  default:
443  break;
444  }
445 
446  m_pImpl->m_aResults.push_back(
447  new ResultListEntry( std::move(pContentProperties) ) );
448  }
449  }
450  catch ( DAVException const & )
451  {
452  }
453  }
454 
455  m_pImpl->m_bCountFinal = true;
456 
457  // Callback possible, because listeners may be informed!
458  aGuard.clear();
459  getResultSet()->rowCountFinal();
460  }
461  return !m_pImpl->m_bThrowException;
462 }
463 
464 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Environment getEnvironment(OUString const &name, OUString const &implementation)
uno::Reference< ucb::XContent > xContent
static const OUString RESOURCETYPE
uno::Reference< uno::XComponentContext > m_xContext
virtual css::uno::Reference< css::sdbc::XRow > queryPropertyValues(sal_uInt32 nIndex) override
static void UCBNamesToDAVNames(const css::uno::Sequence< css::beans::Property > &rProps, std::vector< OUString > &resources, bool bIncludeUnmatched=true)
virtual void releasePropertyValues(sal_uInt32 nIndex) override
virtual bool isCountFinal() override
virtual bool getResult(sal_uInt32 nIndex) override
std::unique_ptr< DataSupplier_Impl > m_pImpl
const OUString & getEscapedTitle() const
DataSupplier_Impl(const uno::Reference< uno::XComponentContext > &rxContext, const rtl::Reference< Content > &rContent, sal_Int32 nOpenMode)
rtl::Reference< Content > m_xContent
virtual sal_uInt32 totalCount() override
virtual sal_uInt32 currentCount() override
virtual css::uno::Reference< css::ucb::XContentIdentifier > queryContentIdentifier(sal_uInt32 nIndex) override
std::unique_ptr< ContentProperties > pData
const OUString & GetPath() const
Definition: SerfUri.hxx:77
rtl::Reference< ResultSet > getResultSet() const
uno::Reference< ucb::XContentIdentifier > xId
virtual void close() override
virtual css::uno::Reference< css::ucb::XContent > queryContent(sal_uInt32 nIndex) override
ResultListEntry(std::unique_ptr< ContentProperties > &&pEntry)
virtual OUString queryContentIdentifierString(sal_uInt32 nIndex) override
css::uno::Reference< css::sdbc::XRow > getPropertyValues(const css::uno::Sequence< css::beans::Property > &rProperties, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
#define SAL_WARN(area, stream)
virtual void validate() override
uno::Reference< sdbc::XRow > xRow
std::vector< ResultListEntry * > ResultList
static OUString unescape(const OUString &string)
Definition: SerfUri.cxx:218