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