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