LibreOffice Module ucb (master)  1
pkgdatasupplier.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 
21 /**************************************************************************
22  TODO
23  **************************************************************************
24 
25  *************************************************************************/
26 
27 #include <osl/diagnose.h>
28 #include <com/sun/star/container/XNamed.hpp>
29 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
30 #include <com/sun/star/ucb/ResultSetException.hpp>
33 #include "pkgdatasupplier.hxx"
34 #include "pkgcontent.hxx"
35 #include "pkgprovider.hxx"
36 
37 #include "../inc/urihelper.hxx"
38 
39 using namespace com::sun::star;
40 using namespace package_ucp;
41 
42 // DataSupplier Implementation.
43 
44 
45 DataSupplier::DataSupplier(
46  const uno::Reference< uno::XComponentContext >& rxContext,
47  const rtl::Reference< Content >& rContent )
48 : m_xContent( rContent ), m_xContext( rxContext ),
49  m_xFolderEnum( rContent->getIterator() ),
50  m_bCountFinal( !m_xFolderEnum.is() ), m_bThrowException( m_bCountFinal )
51 {
52 }
53 
54 
55 // virtual
56 DataSupplier::~DataSupplier()
57 {
58 }
59 
60 
61 // virtual
62 OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
63 {
64  std::unique_lock aGuard( m_aMutex );
65  return queryContentIdentifierStringImpl(aGuard, nIndex);
66 }
67 
68 OUString DataSupplier::queryContentIdentifierStringImpl( std::unique_lock<std::mutex>& rGuard, sal_uInt32 nIndex )
69 {
70  if ( nIndex < m_aResults.size() )
71  {
72  OUString aId = m_aResults[ nIndex ].aURL;
73  if ( !aId.isEmpty() )
74  {
75  // Already cached.
76  return aId;
77  }
78  }
79 
80  if ( getResultImpl( rGuard, nIndex ) )
81  {
82  // Note: getResult fills m_aResults[ nIndex ].aURL.
83  return m_aResults[ nIndex ].aURL;
84  }
85  return OUString();
86 }
87 
88 
89 // virtual
90 uno::Reference< ucb::XContentIdentifier >
92 {
93  std::unique_lock aGuard( m_aMutex );
94  return queryContentIdentifierImpl(aGuard, nIndex);
95 }
96 
97 uno::Reference< ucb::XContentIdentifier >
98 DataSupplier::queryContentIdentifierImpl( std::unique_lock<std::mutex>& rGuard, sal_uInt32 nIndex )
99 {
100  if ( nIndex < m_aResults.size() )
101  {
102  uno::Reference< ucb::XContentIdentifier >& xId
103  = m_aResults[ nIndex ].xId;
104  if ( xId.is() )
105  {
106  // Already cached.
107  return xId;
108  }
109  }
110 
111  OUString aId = queryContentIdentifierStringImpl( rGuard, nIndex );
112  if ( !aId.isEmpty() )
113  {
114  uno::Reference< ucb::XContentIdentifier > xId
115  = new ::ucbhelper::ContentIdentifier( aId );
116  m_aResults[ nIndex ].xId = xId;
117  return xId;
118  }
119  return uno::Reference< ucb::XContentIdentifier >();
120 }
121 
122 
123 // virtual
124 uno::Reference< ucb::XContent > DataSupplier::queryContent(
125  sal_uInt32 nIndex )
126 {
127  std::unique_lock aGuard( m_aMutex );
128 
129  if ( nIndex < m_aResults.size() )
130  {
131  uno::Reference< ucb::XContent >& xContent
132  = m_aResults[ nIndex ].xContent;
133  if ( xContent.is() )
134  {
135  // Already cached.
136  return xContent;
137  }
138  }
139 
140  uno::Reference< ucb::XContentIdentifier > xId
141  = queryContentIdentifierImpl( aGuard, nIndex );
142  if ( xId.is() )
143  {
144  try
145  {
146  uno::Reference< ucb::XContent > xContent
147  = m_xContent->getProvider()->queryContent( xId );
148  m_aResults[ nIndex ].xContent = xContent;
149  return xContent;
150 
151  }
152  catch ( ucb::IllegalIdentifierException const & )
153  {
154  }
155  }
156  return uno::Reference< ucb::XContent >();
157 }
158 
159 
160 // virtual
161 bool DataSupplier::getResult( sal_uInt32 nIndex )
162 {
163  std::unique_lock aGuard( m_aMutex );
164  return getResultImpl(aGuard, nIndex);
165 }
166 
167 bool DataSupplier::getResultImpl( std::unique_lock<std::mutex>& rGuard, sal_uInt32 nIndex )
168 {
169  if ( m_aResults.size() > nIndex )
170  {
171  // Result already present.
172  return true;
173  }
174 
175  // Result not (yet) present.
176 
177  if ( m_bCountFinal )
178  return false;
179 
180  // Try to obtain result...
181 
182  sal_uInt32 nOldCount = m_aResults.size();
183  bool bFound = false;
184  sal_uInt32 nPos = nOldCount;
185 
186  while ( m_xFolderEnum->hasMoreElements() )
187  {
188  try
189  {
190  uno::Reference< container::XNamed > xNamed;
191  m_xFolderEnum->nextElement() >>= xNamed;
192 
193  if ( !xNamed.is() )
194  {
195  OSL_FAIL( "DataSupplier::getResult - Got no XNamed!" );
196  break;
197  }
198 
199  OUString aName = xNamed->getName();
200 
201  if ( aName.isEmpty() )
202  {
203  OSL_FAIL( "DataSupplier::getResult - Empty name!" );
204  break;
205  }
206 
207  // Assemble URL for child.
208  OUString aURL = assembleChildURL( aName );
209 
210  m_aResults.push_back( ResultListEntry( aURL ) );
211 
212  if ( nPos == nIndex )
213  {
214  // Result obtained.
215  bFound = true;
216  break;
217  }
218 
219  nPos++;
220  }
221  catch ( container::NoSuchElementException const & )
222  {
223  m_bThrowException = true;
224  break;
225  }
226  catch ( lang::WrappedTargetException const & )
227  {
228  m_bThrowException = true;
229  break;
230  }
231  }
232 
233  if ( !bFound )
234  m_bCountFinal = true;
235 
237  if ( xResultSet.is() )
238  {
239  // Callbacks follow!
240  rGuard.unlock();
241 
242  if ( nOldCount < m_aResults.size() )
243  xResultSet->rowCountChanged(
244  nOldCount, m_aResults.size() );
245 
246  if ( m_bCountFinal )
247  xResultSet->rowCountFinal();
248 
249  rGuard.lock();
250  }
251 
252  return bFound;
253 }
254 
255 
256 // virtual
258 {
259  std::unique_lock aGuard( m_aMutex );
260 
261  if ( m_bCountFinal )
262  return m_aResults.size();
263 
264  sal_uInt32 nOldCount = m_aResults.size();
265 
266  while ( m_xFolderEnum->hasMoreElements() )
267  {
268  try
269  {
270  uno::Reference< container::XNamed > xNamed;
271  m_xFolderEnum->nextElement() >>= xNamed;
272 
273  if ( !xNamed.is() )
274  {
275  OSL_FAIL( "DataSupplier::getResult - Got no XNamed!" );
276  break;
277  }
278 
279  OUString aName = xNamed->getName();
280 
281  if ( aName.isEmpty() )
282  {
283  OSL_FAIL( "DataSupplier::getResult - Empty name!" );
284  break;
285  }
286 
287  // Assemble URL for child.
288  OUString aURL = assembleChildURL( aName );
289 
290  m_aResults.push_back( ResultListEntry( aURL ) );
291  }
292  catch ( container::NoSuchElementException const & )
293  {
294  m_bThrowException = true;
295  break;
296  }
297  catch ( lang::WrappedTargetException const & )
298  {
299  m_bThrowException = true;
300  break;
301  }
302  }
303 
304  m_bCountFinal = true;
305 
307  if ( xResultSet.is() )
308  {
309  // Callbacks follow!
310  aGuard.unlock();
311 
312  if ( nOldCount < m_aResults.size() )
313  xResultSet->rowCountChanged(
314  nOldCount, m_aResults.size() );
315 
316  xResultSet->rowCountFinal();
317  }
318 
319  return m_aResults.size();
320 }
321 
322 
323 // virtual
325 {
326  return m_aResults.size();
327 }
328 
329 
330 // virtual
332 {
333  return m_bCountFinal;
334 }
335 
336 
337 // virtual
338 uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues(
339  sal_uInt32 nIndex )
340 {
341  std::unique_lock aGuard( m_aMutex );
342 
343  if ( nIndex < m_aResults.size() )
344  {
345  uno::Reference< sdbc::XRow >& xRow = m_aResults[ nIndex ].xRow;
346  if ( xRow.is() )
347  {
348  // Already cached.
349  return xRow;
350  }
351  }
352 
353  if ( getResultImpl( aGuard, nIndex ) )
354  {
355  uno::Reference< sdbc::XRow > xRow = Content::getPropertyValues(
356  m_xContext,
357  getResultSet()->getProperties(),
358  static_cast< ContentProvider * >(
359  m_xContent->getProvider().get() ),
360  queryContentIdentifierStringImpl( aGuard, nIndex ) );
361  m_aResults[ nIndex ].xRow = xRow;
362  return xRow;
363  }
364 
365  return uno::Reference< sdbc::XRow >();
366 }
367 
368 
369 // virtual
370 void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
371 {
372  std::unique_lock aGuard( m_aMutex );
373 
374  if ( nIndex < m_aResults.size() )
375  m_aResults[ nIndex ].xRow.clear();
376 }
377 
378 
379 // virtual
381 {
382 }
383 
384 
385 // virtual
387 {
388  if ( m_bThrowException )
389  throw ucb::ResultSetException();
390 }
391 
392 
393 OUString DataSupplier::assembleChildURL( const OUString& aName )
394 {
395  OUString aURL;
396  OUString aContURL
397  = m_xContent->getIdentifier()->getContentIdentifier();
398  sal_Int32 nParam = aContURL.indexOf( '?' );
399  if ( nParam >= 0 )
400  {
401  aURL = aContURL.copy( 0, nParam );
402 
403  sal_Int32 nPackageUrlEnd = aURL.lastIndexOf( '/' );
404  if ( nPackageUrlEnd != aURL.getLength() - 1 )
405  aURL += "/";
406 
407  aURL += ::ucb_impl::urihelper::encodeSegment( aName ) +
408  aContURL.subView( nParam );
409  }
410  else
411  {
412  aURL = aContURL;
413 
414  sal_Int32 nPackageUrlEnd = aURL.lastIndexOf( '/' );
415  if ( nPackageUrlEnd != aURL.getLength() - 1 )
416  aURL += "/";
417 
418  aURL += ::ucb_impl::urihelper::encodeSegment( aName );
419  }
420  return aURL;
421 }
422 
423 
424 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
URL aURL
Reference< XRow > xRow
bool getResultImpl(std::unique_lock< std::mutex > &, sal_uInt32 nIndex)
static css::uno::Reference< css::sdbc::XRow > getPropertyValues(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Sequence< css::beans::Property > &rProperties, const ContentProperties &rData, const rtl::Reference< ::ucbhelper::ContentProviderImplHelper > &rProvider, const OUString &rContentId)
OUString assembleChildURL(const OUString &aName)
virtual css::uno::Reference< css::ucb::XContent > queryContent(sal_uInt32 nIndex) override
OUString queryContentIdentifierStringImpl(std::unique_lock< std::mutex > &, sal_uInt32 nIndex)
OUString encodeSegment(const OUString &rSegment)
Definition: urihelper.hxx:29
virtual OUString queryContentIdentifierString(sal_uInt32 nIndex) override
virtual css::uno::Reference< css::sdbc::XRow > queryPropertyValues(sal_uInt32 nIndex) override
virtual void validate() override
css::uno::Reference< css::container::XEnumeration > m_xFolderEnum
uno::Reference< ucb::XContent > m_xContent
virtual sal_uInt32 totalCount() override
sal_uInt16 & nParam
virtual void releasePropertyValues(sal_uInt32 nIndex) override
virtual bool getResult(sal_uInt32 nIndex) override
rtl::Reference< ResultSet > getResultSet() const
virtual bool isCountFinal() override
virtual css::uno::Reference< css::ucb::XContentIdentifier > queryContentIdentifier(sal_uInt32 nIndex) override
std::vector< ResultListEntry > m_aResults
css::uno::Reference< css::uno::XComponentContext > m_xContext
css::uno::Reference< css::ucb::XContentIdentifier > queryContentIdentifierImpl(std::unique_lock< std::mutex > &, sal_uInt32 nIndex)
virtual sal_uInt32 currentCount() override
OUString aName
rtl::Reference< Content > m_xContent
virtual void close() override
::rtl::Reference< OContentHelper > xContent
Reference< XComponentContext > m_xContext
sal_uInt16 nPos
Reference< XContentIdentifier > xId
OUString aId