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