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