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