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