1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_ucb.hxx"
26
27 /**************************************************************************
28 TODO
29 **************************************************************************
30
31 *************************************************************************/
32
33 #include <vector>
34 #include <osl/diagnose.h>
35 #include <com/sun/star/container/XEnumeration.hpp>
36 #include <com/sun/star/container/XNamed.hpp>
37 #include <ucbhelper/contentidentifier.hxx>
38 #include <ucbhelper/providerhelper.hxx>
39 #include "pkgdatasupplier.hxx"
40 #include "pkgcontent.hxx"
41 #include "pkgprovider.hxx"
42
43 #include "../inc/urihelper.hxx"
44
45 using namespace com::sun::star;
46 using namespace package_ucp;
47
48 namespace package_ucp
49 {
50
51 //=========================================================================
52 //
53 // struct ResultListEntry.
54 //
55 //=========================================================================
56
57 struct ResultListEntry
58 {
59 rtl::OUString aURL;
60 uno::Reference< ucb::XContentIdentifier > xId;
61 uno::Reference< ucb::XContent > xContent;
62 uno::Reference< sdbc::XRow > xRow;
63
ResultListEntrypackage_ucp::ResultListEntry64 ResultListEntry( const rtl::OUString& rURL ) : aURL( rURL ) {}
65 };
66
67 //=========================================================================
68 //
69 // ResultList.
70 //
71 //=========================================================================
72
73 typedef std::vector< ResultListEntry* > ResultList;
74
75 //=========================================================================
76 //
77 // struct DataSupplier_Impl.
78 //
79 //=========================================================================
80
81 struct DataSupplier_Impl
82 {
83 osl::Mutex m_aMutex;
84 ResultList m_aResults;
85 rtl::Reference< Content > m_xContent;
86 uno::Reference< lang::XMultiServiceFactory > m_xSMgr;
87 uno::Reference< container::XEnumeration > m_xFolderEnum;
88 sal_Int32 m_nOpenMode;
89 sal_Bool m_bCountFinal;
90 sal_Bool m_bThrowException;
91
DataSupplier_Implpackage_ucp::DataSupplier_Impl92 DataSupplier_Impl(
93 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
94 const rtl::Reference< Content >& rContent,
95 sal_Int32 nOpenMode )
96 : m_xContent( rContent ), m_xSMgr( rxSMgr ),
97 m_xFolderEnum( rContent->getIterator() ), m_nOpenMode( nOpenMode ),
98 m_bCountFinal( !m_xFolderEnum.is() ), m_bThrowException( m_bCountFinal )
99 {}
100 ~DataSupplier_Impl();
101 };
102
103 //=========================================================================
~DataSupplier_Impl()104 DataSupplier_Impl::~DataSupplier_Impl()
105 {
106 ResultList::const_iterator it = m_aResults.begin();
107 ResultList::const_iterator end = m_aResults.end();
108
109 while ( it != end )
110 {
111 delete (*it);
112 it++;
113 }
114 }
115
116 }
117
118 //=========================================================================
119 //=========================================================================
120 //
121 // DataSupplier Implementation.
122 //
123 //=========================================================================
124 //=========================================================================
125
DataSupplier(const uno::Reference<lang::XMultiServiceFactory> & rxSMgr,const rtl::Reference<Content> & rContent,sal_Int32 nOpenMode)126 DataSupplier::DataSupplier(
127 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
128 const rtl::Reference< Content >& rContent,
129 sal_Int32 nOpenMode )
130 : m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) )
131 {
132 }
133
134 //=========================================================================
135 // virtual
~DataSupplier()136 DataSupplier::~DataSupplier()
137 {
138 delete m_pImpl;
139 }
140
141 //=========================================================================
142 // virtual
queryContentIdentifierString(sal_uInt32 nIndex)143 rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
144 {
145 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
146
147 if ( nIndex < m_pImpl->m_aResults.size() )
148 {
149 rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aURL;
150 if ( aId.getLength() )
151 {
152 // Already cached.
153 return aId;
154 }
155 }
156
157 if ( getResult( nIndex ) )
158 {
159 // Note: getResult fills m_pImpl->m_aResults[ nIndex ]->aURL.
160 return m_pImpl->m_aResults[ nIndex ]->aURL;
161 }
162 return rtl::OUString();
163 }
164
165 //=========================================================================
166 // virtual
167 uno::Reference< ucb::XContentIdentifier >
queryContentIdentifier(sal_uInt32 nIndex)168 DataSupplier::queryContentIdentifier( sal_uInt32 nIndex )
169 {
170 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
171
172 if ( nIndex < m_pImpl->m_aResults.size() )
173 {
174 uno::Reference< ucb::XContentIdentifier > xId
175 = m_pImpl->m_aResults[ nIndex ]->xId;
176 if ( xId.is() )
177 {
178 // Already cached.
179 return xId;
180 }
181 }
182
183 rtl::OUString aId = queryContentIdentifierString( nIndex );
184 if ( aId.getLength() )
185 {
186 uno::Reference< ucb::XContentIdentifier > xId
187 = new ::ucbhelper::ContentIdentifier( aId );
188 m_pImpl->m_aResults[ nIndex ]->xId = xId;
189 return xId;
190 }
191 return uno::Reference< ucb::XContentIdentifier >();
192 }
193
194 //=========================================================================
195 // virtual
queryContent(sal_uInt32 nIndex)196 uno::Reference< ucb::XContent > DataSupplier::queryContent(
197 sal_uInt32 nIndex )
198 {
199 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
200
201 if ( nIndex < m_pImpl->m_aResults.size() )
202 {
203 uno::Reference< ucb::XContent > xContent
204 = m_pImpl->m_aResults[ nIndex ]->xContent;
205 if ( xContent.is() )
206 {
207 // Already cached.
208 return xContent;
209 }
210 }
211
212 uno::Reference< ucb::XContentIdentifier > xId
213 = queryContentIdentifier( nIndex );
214 if ( xId.is() )
215 {
216 try
217 {
218 uno::Reference< ucb::XContent > xContent
219 = m_pImpl->m_xContent->getProvider()->queryContent( xId );
220 m_pImpl->m_aResults[ nIndex ]->xContent = xContent;
221 return xContent;
222
223 }
224 catch ( ucb::IllegalIdentifierException const & )
225 {
226 }
227 }
228 return uno::Reference< ucb::XContent >();
229 }
230
231 //=========================================================================
232 // virtual
getResult(sal_uInt32 nIndex)233 sal_Bool DataSupplier::getResult( sal_uInt32 nIndex )
234 {
235 osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
236
237 if ( m_pImpl->m_aResults.size() > nIndex )
238 {
239 // Result already present.
240 return sal_True;
241 }
242
243 // Result not (yet) present.
244
245 if ( m_pImpl->m_bCountFinal )
246 return sal_False;
247
248 // Try to obtain result...
249
250 sal_uInt32 nOldCount = m_pImpl->m_aResults.size();
251 sal_Bool bFound = sal_False;
252 sal_uInt32 nPos = nOldCount;
253
254 while ( m_pImpl->m_xFolderEnum->hasMoreElements() )
255 {
256 try
257 {
258 uno::Reference< container::XNamed > xNamed;
259 m_pImpl->m_xFolderEnum->nextElement() >>= xNamed;
260
261 if ( !xNamed.is() )
262 {
263 OSL_ENSURE( sal_False,
264 "DataSupplier::getResult - Got no XNamed!" );
265 break;
266 }
267
268 rtl::OUString aName = xNamed->getName();
269
270 if ( !aName.getLength() )
271 {
272 OSL_ENSURE( sal_False,
273 "DataSupplier::getResult - Empty name!" );
274 break;
275 }
276
277 // Assemble URL for child.
278 rtl::OUString aURL = assembleChildURL( aName );
279
280 m_pImpl->m_aResults.push_back( new ResultListEntry( aURL ) );
281
282 if ( nPos == nIndex )
283 {
284 // Result obtained.
285 bFound = sal_True;
286 break;
287 }
288
289 nPos++;
290 }
291 catch ( container::NoSuchElementException const & )
292 {
293 m_pImpl->m_bThrowException = sal_True;
294 break;
295 }
296 catch ( lang::WrappedTargetException const & )
297 {
298 m_pImpl->m_bThrowException = sal_True;
299 break;
300 }
301 }
302
303 if ( !bFound )
304 m_pImpl->m_bCountFinal = sal_True;
305
306 rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get();
307 if ( xResultSet.is() )
308 {
309 // Callbacks follow!
310 aGuard.clear();
311
312 if ( nOldCount < m_pImpl->m_aResults.size() )
313 xResultSet->rowCountChanged(
314 nOldCount, m_pImpl->m_aResults.size() );
315
316 if ( m_pImpl->m_bCountFinal )
317 xResultSet->rowCountFinal();
318 }
319
320 return bFound;
321 }
322
323 //=========================================================================
324 // virtual
totalCount()325 sal_uInt32 DataSupplier::totalCount()
326 {
327 osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
328
329 if ( m_pImpl->m_bCountFinal )
330 return m_pImpl->m_aResults.size();
331
332 sal_uInt32 nOldCount = m_pImpl->m_aResults.size();
333
334 while ( m_pImpl->m_xFolderEnum->hasMoreElements() )
335 {
336 try
337 {
338 uno::Reference< container::XNamed > xNamed;
339 m_pImpl->m_xFolderEnum->nextElement() >>= xNamed;
340
341 if ( !xNamed.is() )
342 {
343 OSL_ENSURE( sal_False,
344 "DataSupplier::getResult - Got no XNamed!" );
345 break;
346 }
347
348 rtl::OUString aName = xNamed->getName();
349
350 if ( !aName.getLength() )
351 {
352 OSL_ENSURE( sal_False,
353 "DataSupplier::getResult - Empty name!" );
354 break;
355 }
356
357 // Assemble URL for child.
358 rtl::OUString aURL = assembleChildURL( aName );
359
360 m_pImpl->m_aResults.push_back( new ResultListEntry( aURL ) );
361 }
362 catch ( container::NoSuchElementException const & )
363 {
364 m_pImpl->m_bThrowException = sal_True;
365 break;
366 }
367 catch ( lang::WrappedTargetException const & )
368 {
369 m_pImpl->m_bThrowException = sal_True;
370 break;
371 }
372 }
373
374 m_pImpl->m_bCountFinal = sal_True;
375
376 rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get();
377 if ( xResultSet.is() )
378 {
379 // Callbacks follow!
380 aGuard.clear();
381
382 if ( nOldCount < m_pImpl->m_aResults.size() )
383 xResultSet->rowCountChanged(
384 nOldCount, m_pImpl->m_aResults.size() );
385
386 xResultSet->rowCountFinal();
387 }
388
389 return m_pImpl->m_aResults.size();
390 }
391
392 //=========================================================================
393 // virtual
currentCount()394 sal_uInt32 DataSupplier::currentCount()
395 {
396 return m_pImpl->m_aResults.size();
397 }
398
399 //=========================================================================
400 // virtual
isCountFinal()401 sal_Bool DataSupplier::isCountFinal()
402 {
403 return m_pImpl->m_bCountFinal;
404 }
405
406 //=========================================================================
407 // virtual
queryPropertyValues(sal_uInt32 nIndex)408 uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues(
409 sal_uInt32 nIndex )
410 {
411 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
412
413 if ( nIndex < m_pImpl->m_aResults.size() )
414 {
415 uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow;
416 if ( xRow.is() )
417 {
418 // Already cached.
419 return xRow;
420 }
421 }
422
423 if ( getResult( nIndex ) )
424 {
425 uno::Reference< sdbc::XRow > xRow = Content::getPropertyValues(
426 m_pImpl->m_xSMgr,
427 getResultSet()->getProperties(),
428 static_cast< ContentProvider * >(
429 m_pImpl->m_xContent->getProvider().get() ),
430 queryContentIdentifierString( nIndex ) );
431 m_pImpl->m_aResults[ nIndex ]->xRow = xRow;
432 return xRow;
433 }
434
435 return uno::Reference< sdbc::XRow >();
436 }
437
438 //=========================================================================
439 // virtual
releasePropertyValues(sal_uInt32 nIndex)440 void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
441 {
442 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
443
444 if ( nIndex < m_pImpl->m_aResults.size() )
445 m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >();
446 }
447
448 //=========================================================================
449 // virtual
close()450 void DataSupplier::close()
451 {
452 }
453
454 //=========================================================================
455 // virtual
validate()456 void DataSupplier::validate()
457 throw( ucb::ResultSetException )
458 {
459 if ( m_pImpl->m_bThrowException )
460 throw ucb::ResultSetException();
461 }
462
463 //=========================================================================
assembleChildURL(const::rtl::OUString & aName)464 ::rtl::OUString DataSupplier::assembleChildURL( const ::rtl::OUString& aName )
465 {
466 rtl::OUString aURL;
467 rtl::OUString aContURL
468 = m_pImpl->m_xContent->getIdentifier()->getContentIdentifier();
469 sal_Int32 nParam = aContURL.indexOf( '?' );
470 if ( nParam >= 0 )
471 {
472 aURL = aContURL.copy( 0, nParam );
473
474 sal_Int32 nPackageUrlEnd = aURL.lastIndexOf( '/' );
475 if ( nPackageUrlEnd != aURL.getLength() - 1 )
476 aURL += rtl::OUString::createFromAscii( "/" );
477
478 aURL += ::ucb_impl::urihelper::encodeSegment( aName );
479 aURL += aContURL.copy( nParam );
480 }
481 else
482 {
483 aURL = aContURL;
484
485 sal_Int32 nPackageUrlEnd = aURL.lastIndexOf( '/' );
486 if ( nPackageUrlEnd != aURL.getLength() - 1 )
487 aURL += rtl::OUString::createFromAscii( "/" );
488
489 aURL += ::ucb_impl::urihelper::encodeSegment( aName );
490 }
491 return aURL;
492 }
493
494
495