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