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 
64     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 
92     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 //=========================================================================
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 
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
136 DataSupplier::~DataSupplier()
137 {
138 	delete m_pImpl;
139 }
140 
141 //=========================================================================
142 // virtual
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 >
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
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
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
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
394 sal_uInt32 DataSupplier::currentCount()
395 {
396 	return m_pImpl->m_aResults.size();
397 }
398 
399 //=========================================================================
400 // virtual
401 sal_Bool DataSupplier::isCountFinal()
402 {
403 	return m_pImpl->m_bCountFinal;
404 }
405 
406 //=========================================================================
407 // virtual
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
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
450 void DataSupplier::close()
451 {
452 }
453 
454 //=========================================================================
455 // virtual
456 void DataSupplier::validate()
457     throw( ucb::ResultSetException )
458 {
459     if ( m_pImpl->m_bThrowException )
460         throw ucb::ResultSetException();
461 }
462 
463 //=========================================================================
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