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 
39 #include "osl/diagnose.h"
40 #include "ucbhelper/contentidentifier.hxx"
41 
42 #include "tdoc_datasupplier.hxx"
43 #include "tdoc_content.hxx"
44 
45 using namespace com::sun::star;
46 using namespace tdoc_ucp;
47 
48 namespace tdoc_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::Sequence< rtl::OUString > *             m_pNamesOfChildren;
88     sal_Int32                                    m_nOpenMode;
89     bool                                         m_bCountFinal;
90     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_pNamesOfChildren( 0 ), m_nOpenMode( nOpenMode ),
98       m_bCountFinal( false ), m_bThrowException( false )
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     delete m_pNamesOfChildren;
116 }
117 
118 }
119 
120 //=========================================================================
121 //=========================================================================
122 //
123 // DataSupplier Implementation.
124 //
125 //=========================================================================
126 //=========================================================================
127 
128 ResultSetDataSupplier::ResultSetDataSupplier(
129                 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
130                 const rtl::Reference< Content >& rContent,
131                 sal_Int32 nOpenMode )
132 : m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) )
133 {
134 }
135 
136 //=========================================================================
137 // virtual
138 ResultSetDataSupplier::~ResultSetDataSupplier()
139 {
140 	delete m_pImpl;
141 }
142 
143 //=========================================================================
144 // virtual
145 rtl::OUString
146 ResultSetDataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
147 {
148 	osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
149 
150 	if ( nIndex < m_pImpl->m_aResults.size() )
151 	{
152         rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aURL;
153 		if ( aId.getLength() )
154 		{
155 			// Already cached.
156 			return aId;
157 		}
158 	}
159 
160 	if ( getResult( nIndex ) )
161 	{
162 		// Note: getResult fills m_pImpl->m_aResults[ nIndex ]->aURL.
163 		return m_pImpl->m_aResults[ nIndex ]->aURL;
164 	}
165     return rtl::OUString();
166 }
167 
168 //=========================================================================
169 // virtual
170 uno::Reference< ucb::XContentIdentifier >
171 ResultSetDataSupplier::queryContentIdentifier( sal_uInt32 nIndex )
172 {
173 	osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
174 
175 	if ( nIndex < m_pImpl->m_aResults.size() )
176 	{
177         uno::Reference< ucb::XContentIdentifier > xId
178 								= m_pImpl->m_aResults[ nIndex ]->xId;
179 		if ( xId.is() )
180 		{
181 			// Already cached.
182 			return xId;
183 		}
184 	}
185 
186     rtl::OUString aId = queryContentIdentifierString( nIndex );
187 	if ( aId.getLength() )
188 	{
189         uno::Reference< ucb::XContentIdentifier > xId
190             = new ::ucbhelper::ContentIdentifier( aId );
191 		m_pImpl->m_aResults[ nIndex ]->xId = xId;
192 		return xId;
193 	}
194     return uno::Reference< ucb::XContentIdentifier >();
195 }
196 
197 //=========================================================================
198 // virtual
199 uno::Reference< ucb::XContent >
200 ResultSetDataSupplier::queryContent( sal_uInt32 nIndex )
201 {
202 	osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
203 
204 	if ( nIndex < m_pImpl->m_aResults.size() )
205 	{
206         uno::Reference< ucb::XContent > xContent
207 								= m_pImpl->m_aResults[ nIndex ]->xContent;
208 		if ( xContent.is() )
209 		{
210 			// Already cached.
211 			return xContent;
212 		}
213 	}
214 
215     uno::Reference< ucb::XContentIdentifier > xId
216         = queryContentIdentifier( nIndex );
217 	if ( xId.is() )
218 	{
219 		try
220 		{
221             uno::Reference< ucb::XContent > xContent
222 				= m_pImpl->m_xContent->getProvider()->queryContent( xId );
223 			m_pImpl->m_aResults[ nIndex ]->xContent = xContent;
224 			return xContent;
225 
226 		}
227         catch ( ucb::IllegalIdentifierException const & )
228 		{
229 		}
230 	}
231     return uno::Reference< ucb::XContent >();
232 }
233 
234 //=========================================================================
235 // virtual
236 sal_Bool ResultSetDataSupplier::getResult( sal_uInt32 nIndex )
237 {
238 	osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
239 
240 	if ( m_pImpl->m_aResults.size() > nIndex )
241 	{
242 		// Result already present.
243 		return sal_True;
244 	}
245 
246 	// Result not (yet) present.
247 
248 	if ( m_pImpl->m_bCountFinal )
249 		return sal_False;
250 
251 	// Try to obtain result...
252 
253 	sal_uInt32 nOldCount = m_pImpl->m_aResults.size();
254     bool bFound = false;
255 
256     if ( queryNamesOfChildren() )
257     {
258         for ( sal_uInt32 n = nOldCount;
259               n < sal::static_int_cast<sal_uInt32>(
260                       m_pImpl->m_pNamesOfChildren->getLength());
261               ++n )
262         {
263             const rtl::OUString & rName
264                 = m_pImpl->m_pNamesOfChildren->getConstArray()[ n ];
265 
266             if ( !rName.getLength() )
267             {
268                 OSL_ENSURE( sal_False,
269                             "ResultDataSupplier::getResult - Empty name!" );
270                 break;
271             }
272 
273             // Assemble URL for child.
274             rtl::OUString aURL = assembleChildURL( rName );
275 
276             m_pImpl->m_aResults.push_back( new ResultListEntry( aURL ) );
277 
278             if ( n == nIndex )
279             {
280                 // Result obtained.
281                 bFound = true;
282                 break;
283             }
284         }
285     }
286 
287 	if ( !bFound )
288 		m_pImpl->m_bCountFinal = sal_True;
289 
290     rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get();
291     if ( xResultSet.is() )
292 	{
293 		// Callbacks follow!
294 		aGuard.clear();
295 
296 		if ( nOldCount < m_pImpl->m_aResults.size() )
297             xResultSet->rowCountChanged( nOldCount, m_pImpl->m_aResults.size() );
298 
299 		if ( m_pImpl->m_bCountFinal )
300 			xResultSet->rowCountFinal();
301 	}
302 
303 	return bFound;
304 }
305 
306 //=========================================================================
307 // virtual
308 sal_uInt32 ResultSetDataSupplier::totalCount()
309 {
310 	osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
311 
312 	if ( m_pImpl->m_bCountFinal )
313 		return m_pImpl->m_aResults.size();
314 
315 	sal_uInt32 nOldCount = m_pImpl->m_aResults.size();
316 
317     if ( queryNamesOfChildren() )
318     {
319         for ( sal_uInt32 n = nOldCount;
320               n < sal::static_int_cast<sal_uInt32>(
321                       m_pImpl->m_pNamesOfChildren->getLength());
322               ++n )
323         {
324             const rtl::OUString & rName
325                 = m_pImpl->m_pNamesOfChildren->getConstArray()[ n ];
326 
327             if ( !rName.getLength() )
328             {
329                 OSL_ENSURE( sal_False,
330                             "ResultDataSupplier::getResult - Empty name!" );
331                 break;
332             }
333 
334             // Assemble URL for child.
335             rtl::OUString aURL = assembleChildURL( rName );
336 
337             m_pImpl->m_aResults.push_back( new ResultListEntry( aURL ) );
338         }
339     }
340 
341 	m_pImpl->m_bCountFinal = sal_True;
342 
343     rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get();
344     if ( xResultSet.is() )
345 	{
346 		// Callbacks follow!
347 		aGuard.clear();
348 
349 		if ( nOldCount < m_pImpl->m_aResults.size() )
350             xResultSet->rowCountChanged( nOldCount, m_pImpl->m_aResults.size() );
351 
352 		xResultSet->rowCountFinal();
353 	}
354 
355 	return m_pImpl->m_aResults.size();
356 }
357 
358 //=========================================================================
359 // virtual
360 sal_uInt32 ResultSetDataSupplier::currentCount()
361 {
362 	return m_pImpl->m_aResults.size();
363 }
364 
365 //=========================================================================
366 // virtual
367 sal_Bool ResultSetDataSupplier::isCountFinal()
368 {
369 	return m_pImpl->m_bCountFinal;
370 }
371 
372 //=========================================================================
373 // virtual
374 uno::Reference< sdbc::XRow >
375 ResultSetDataSupplier::queryPropertyValues( sal_uInt32 nIndex  )
376 {
377 	osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
378 
379 	if ( nIndex < m_pImpl->m_aResults.size() )
380 	{
381         uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow;
382 		if ( xRow.is() )
383 		{
384 			// Already cached.
385 			return xRow;
386 		}
387 	}
388 
389 	if ( getResult( nIndex ) )
390 	{
391         uno::Reference< sdbc::XRow > xRow = Content::getPropertyValues(
392 						m_pImpl->m_xSMgr,
393 						getResultSet()->getProperties(),
394                         m_pImpl->m_xContent->getContentProvider().get(),
395 						queryContentIdentifierString( nIndex ) );
396 		m_pImpl->m_aResults[ nIndex ]->xRow = xRow;
397 		return xRow;
398 	}
399 
400     return uno::Reference< sdbc::XRow >();
401 }
402 
403 //=========================================================================
404 // virtual
405 void ResultSetDataSupplier::releasePropertyValues( sal_uInt32 nIndex )
406 {
407 	osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
408 
409 	if ( nIndex < m_pImpl->m_aResults.size() )
410         m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >();
411 }
412 
413 //=========================================================================
414 // virtual
415 void ResultSetDataSupplier::close()
416 {
417 }
418 
419 //=========================================================================
420 // virtual
421 void ResultSetDataSupplier::validate()
422     throw( ucb::ResultSetException )
423 {
424     if ( m_pImpl->m_bThrowException )
425         throw ucb::ResultSetException();
426 }
427 
428 //=========================================================================
429 bool ResultSetDataSupplier::queryNamesOfChildren()
430 {
431     osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
432 
433     if ( m_pImpl->m_pNamesOfChildren == 0 )
434     {
435         uno::Sequence< rtl::OUString > * pNamesOfChildren
436             = new uno::Sequence< rtl::OUString >();
437 
438         if ( !m_pImpl->m_xContent->getContentProvider()->queryNamesOfChildren(
439                 m_pImpl->m_xContent->getIdentifier()->getContentIdentifier(),
440                 *pNamesOfChildren ) )
441         {
442             OSL_ENSURE( false, "Got no list of children!" );
443             m_pImpl->m_bThrowException = sal_True;
444             return false;
445         }
446         else
447         {
448             m_pImpl->m_pNamesOfChildren = pNamesOfChildren;
449         }
450     }
451     return true;
452 }
453 
454 //=========================================================================
455 ::rtl::OUString
456 ResultSetDataSupplier::assembleChildURL( const ::rtl::OUString& aName )
457 {
458     rtl::OUString aContURL
459         = m_pImpl->m_xContent->getIdentifier()->getContentIdentifier();
460     rtl::OUString aURL( aContURL );
461 
462     sal_Int32 nUrlEnd = aURL.lastIndexOf( '/' );
463     if ( nUrlEnd != aURL.getLength() - 1 )
464         aURL += rtl::OUString::createFromAscii( "/" );
465 
466     aURL += aName;
467 	return aURL;
468 }
469