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 #include <osl/diagnose.h>
33 #include <com/sun/star/ucb/OpenMode.hpp>
34 #include <ucbhelper/contentidentifier.hxx>
35 #include <ucbhelper/providerhelper.hxx>
36 #include "webdavdatasupplier.hxx"
37 #include "webdavcontent.hxx"
38 #include "ContentProperties.hxx"
39 #ifndef _WEBDAV_SESSION_HXX
40 #include "DAVSession.hxx"
41 #endif
42 #include "SerfUri.hxx"
43
44 using namespace com::sun::star;
45 using namespace http_dav_ucp;
46
47 namespace http_dav_ucp
48 {
49
50 //=========================================================================
51 //
52 // struct ResultListEntry.
53 //
54 //=========================================================================
55
56 struct ResultListEntry
57 {
58 rtl::OUString aId;
59 uno::Reference< ucb::XContentIdentifier > xId;
60 uno::Reference< ucb::XContent > xContent;
61 uno::Reference< sdbc::XRow > xRow;
62 const ContentProperties* pData;
63
ResultListEntryhttp_dav_ucp::ResultListEntry64 ResultListEntry( const ContentProperties* pEntry ) : pData( pEntry ) {};
~ResultListEntryhttp_dav_ucp::ResultListEntry65 ~ResultListEntry() { delete pData; }
66 };
67
68 //=========================================================================
69 //
70 // ResultList.
71 //
72 //=========================================================================
73
74 typedef std::vector< ResultListEntry* > ResultList;
75
76 //=========================================================================
77 //
78 // struct DataSupplier_Impl.
79 //
80 //=========================================================================
81
82 struct DataSupplier_Impl
83 {
84 osl::Mutex m_aMutex;
85 ResultList m_aResults;
86 rtl::Reference< Content > m_xContent;
87 uno::Reference< lang::XMultiServiceFactory > m_xSMgr;
88 sal_Int32 m_nOpenMode;
89 sal_Bool m_bCountFinal;
90 sal_Bool m_bThrowException;
91
DataSupplier_Implhttp_dav_ucp::DataSupplier_Impl92 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 ), m_nOpenMode( nOpenMode ),
97 m_bCountFinal( sal_False ), m_bThrowException( sal_False ) {}
98 ~DataSupplier_Impl();
99 };
100
101 //=========================================================================
~DataSupplier_Impl()102 DataSupplier_Impl::~DataSupplier_Impl()
103 {
104 ResultList::const_iterator it = m_aResults.begin();
105 ResultList::const_iterator end = m_aResults.end();
106
107 while ( it != end )
108 {
109 delete (*it);
110 it++;
111 }
112 }
113
114 }
115
116 //=========================================================================
117 //=========================================================================
118 //
119 // DataSupplier Implementation.
120 //
121 //=========================================================================
122 //=========================================================================
123
DataSupplier(const uno::Reference<lang::XMultiServiceFactory> & rxSMgr,const rtl::Reference<Content> & rContent,sal_Int32 nOpenMode)124 DataSupplier::DataSupplier(
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
~DataSupplier()134 DataSupplier::~DataSupplier()
135 {
136 delete m_pImpl;
137 }
138
139 //=========================================================================
140 // virtual
queryContentIdentifierString(sal_uInt32 nIndex)141 rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
142 {
143 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
144
145 if ( nIndex < m_pImpl->m_aResults.size() )
146 {
147 rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aId;
148 if ( aId.getLength() )
149 {
150 // Already cached.
151 return aId;
152 }
153 }
154
155 if ( getResult( nIndex ) )
156 {
157 rtl::OUString aId = m_pImpl->m_xContent->getResourceAccess().getURL();
158
159 const ContentProperties& props
160 = *( m_pImpl->m_aResults[ nIndex ]->pData );
161
162 if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() )
163 aId += rtl::OUString::createFromAscii( "/" );
164
165 aId += props.getEscapedTitle();
166
167 if ( props.isTrailingSlash() )
168 aId += rtl::OUString::createFromAscii( "/" );
169
170 m_pImpl->m_aResults[ nIndex ]->aId = aId;
171 return aId;
172 }
173 return rtl::OUString();
174 }
175
176 //=========================================================================
177 // virtual
178 uno::Reference< ucb::XContentIdentifier >
queryContentIdentifier(sal_uInt32 nIndex)179 DataSupplier::queryContentIdentifier( sal_uInt32 nIndex )
180 {
181 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
182
183 if ( nIndex < m_pImpl->m_aResults.size() )
184 {
185 uno::Reference< ucb::XContentIdentifier > xId
186 = m_pImpl->m_aResults[ nIndex ]->xId;
187 if ( xId.is() )
188 {
189 // Already cached.
190 return xId;
191 }
192 }
193
194 rtl::OUString aId = queryContentIdentifierString( nIndex );
195 if ( aId.getLength() )
196 {
197 uno::Reference< ucb::XContentIdentifier > xId
198 = new ::ucbhelper::ContentIdentifier( aId );
199 m_pImpl->m_aResults[ nIndex ]->xId = xId;
200 return xId;
201 }
202 return uno::Reference< ucb::XContentIdentifier >();
203 }
204
205 //=========================================================================
206 // virtual
207 uno::Reference< ucb::XContent >
queryContent(sal_uInt32 nIndex)208 DataSupplier::queryContent( sal_uInt32 nIndex )
209 {
210 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
211
212 if ( nIndex < m_pImpl->m_aResults.size() )
213 {
214 uno::Reference< ucb::XContent > xContent
215 = m_pImpl->m_aResults[ nIndex ]->xContent;
216 if ( xContent.is() )
217 {
218 // Already cached.
219 return xContent;
220 }
221 }
222
223 uno::Reference< ucb::XContentIdentifier > xId
224 = queryContentIdentifier( nIndex );
225 if ( xId.is() )
226 {
227 try
228 {
229 uno::Reference< ucb::XContent > xContent
230 = m_pImpl->m_xContent->getProvider()->queryContent( xId );
231 m_pImpl->m_aResults[ nIndex ]->xContent = xContent;
232 return xContent;
233
234 }
235 catch ( ucb::IllegalIdentifierException& )
236 {
237 }
238 }
239 return uno::Reference< ucb::XContent >();
240 }
241
242 //=========================================================================
243 // virtual
getResult(sal_uInt32 nIndex)244 sal_Bool DataSupplier::getResult( sal_uInt32 nIndex )
245 {
246 osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
247
248 if ( m_pImpl->m_aResults.size() > nIndex )
249 {
250 // Result already present.
251 return sal_True;
252 }
253
254 // Obtain values...
255 if ( getData() )
256 {
257 if ( m_pImpl->m_aResults.size() > nIndex )
258 {
259 // Result already present.
260 return sal_True;
261 }
262 }
263
264 return sal_False;
265 }
266
267 //=========================================================================
268 // virtual
totalCount()269 sal_uInt32 DataSupplier::totalCount()
270 {
271 // Obtain values...
272 getData();
273
274 return m_pImpl->m_aResults.size();
275 }
276
277 //=========================================================================
278 // virtual
currentCount()279 sal_uInt32 DataSupplier::currentCount()
280 {
281 return m_pImpl->m_aResults.size();
282 }
283
284 //=========================================================================
285 // virtual
isCountFinal()286 sal_Bool DataSupplier::isCountFinal()
287 {
288 return m_pImpl->m_bCountFinal;
289 }
290
291 //=========================================================================
292 // virtual
queryPropertyValues(sal_uInt32 nIndex)293 uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues(
294 sal_uInt32 nIndex )
295 {
296 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
297
298 if ( nIndex < m_pImpl->m_aResults.size() )
299 {
300 uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow;
301 if ( xRow.is() )
302 {
303 // Already cached.
304 return xRow;
305 }
306 }
307
308 if ( getResult( nIndex ) )
309 {
310 uno::Reference< sdbc::XRow > xRow
311 = Content::getPropertyValues(
312 m_pImpl->m_xSMgr,
313 getResultSet()->getProperties(),
314 *(m_pImpl->m_aResults[ nIndex ]->pData),
315 rtl::Reference< ::ucbhelper::ContentProviderImplHelper >(
316 m_pImpl->m_xContent->getProvider().get() ),
317 queryContentIdentifierString( nIndex ) );
318 m_pImpl->m_aResults[ nIndex ]->xRow = xRow;
319 return xRow;
320 }
321
322 return uno::Reference< sdbc::XRow >();
323 }
324
325 //=========================================================================
326 // virtual
releasePropertyValues(sal_uInt32 nIndex)327 void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
328 {
329 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
330
331 if ( nIndex < m_pImpl->m_aResults.size() )
332 m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >();
333 }
334
335 //=========================================================================
336 // virtual
close()337 void DataSupplier::close()
338 {
339 }
340
341 //=========================================================================
342 // virtual
validate()343 void DataSupplier::validate()
344 throw( ucb::ResultSetException )
345 {
346 if ( m_pImpl->m_bThrowException )
347 throw ucb::ResultSetException();
348 }
349
350 //=========================================================================
getData()351 sal_Bool DataSupplier::getData()
352 {
353 osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
354
355 if ( !m_pImpl->m_bCountFinal )
356 {
357 std::vector< rtl::OUString > propertyNames;
358 ContentProperties::UCBNamesToDAVNames(
359 getResultSet()->getProperties(), propertyNames );
360
361 // Append "resourcetype", if not already present. It's value is
362 // needed to get a valid ContentProperties::pIsFolder value, which
363 // is needed for OpenMode handling.
364
365 std::vector< rtl::OUString >::const_iterator it
366 = propertyNames.begin();
367 std::vector< rtl::OUString >::const_iterator end
368 = propertyNames.end();
369
370 while ( it != end )
371 {
372 if ( (*it).equals( DAVProperties::RESOURCETYPE ) )
373 break;
374
375 it++;
376 }
377
378 if ( it == end )
379 propertyNames.push_back( DAVProperties::RESOURCETYPE );
380
381 std::vector< DAVResource > resources;
382 try
383 {
384 // propfind depth 1, get property values for parent AND for each
385 // child
386 m_pImpl->m_xContent->getResourceAccess()
387 .PROPFIND( DAVONE,
388 propertyNames,
389 resources,
390 getResultSet()->getEnvironment() );
391 }
392 catch ( DAVException & )
393 {
394 // OSL_ENSURE( sal_False, "PROPFIND : DAVException" );
395 m_pImpl->m_bThrowException = sal_True;
396 }
397
398 if ( !m_pImpl->m_bThrowException )
399 {
400 try
401 {
402 SerfUri aURI(
403 m_pImpl->m_xContent->getResourceAccess().getURL() );
404 rtl::OUString aPath = aURI.GetPath();
405
406 if ( aPath.getStr()[ aPath.getLength() - 1 ]
407 == sal_Unicode( '/' ) )
408 aPath = aPath.copy( 0, aPath.getLength() - 1 );
409
410 aPath = SerfUri::unescape( aPath );
411 bool bFoundParent = false;
412
413 for ( sal_uInt32 n = 0; n < resources.size(); ++n )
414 {
415 const DAVResource & rRes = resources[ n ];
416
417 // Filter parent, which is contained somewhere(!) in
418 // the vector.
419 if ( !bFoundParent )
420 {
421 try
422 {
423 SerfUri aCurrURI( rRes.uri );
424 rtl::OUString aCurrPath = aCurrURI.GetPath();
425 if ( aCurrPath.getStr()[
426 aCurrPath.getLength() - 1 ]
427 == sal_Unicode( '/' ) )
428 aCurrPath
429 = aCurrPath.copy(
430 0,
431 aCurrPath.getLength() - 1 );
432
433 aCurrPath = SerfUri::unescape( aCurrPath );
434 if ( aPath == aCurrPath )
435 {
436 bFoundParent = true;
437 continue;
438 }
439 }
440 catch ( DAVException const & )
441 {
442 // do nothing, ignore error. continue.
443 }
444 }
445
446 ContentProperties* pContentProperties
447 = new ContentProperties( rRes );
448
449 // Check resource against open mode.
450 switch ( m_pImpl->m_nOpenMode )
451 {
452 case ucb::OpenMode::FOLDERS:
453 {
454 sal_Bool bFolder = sal_False;
455
456 const uno::Any & rValue
457 = pContentProperties->getValue(
458 rtl::OUString(
459 RTL_CONSTASCII_USTRINGPARAM(
460 "IsFolder" ) ) );
461 rValue >>= bFolder;
462
463 if ( !bFolder )
464 continue;
465
466 break;
467 }
468
469 case ucb::OpenMode::DOCUMENTS:
470 {
471 sal_Bool bDocument = sal_False;
472
473 const uno::Any & rValue
474 = pContentProperties->getValue(
475 rtl::OUString(
476 RTL_CONSTASCII_USTRINGPARAM(
477 "IsDocument" ) ) );
478 rValue >>= bDocument;
479
480 if ( !bDocument )
481 continue;
482
483 break;
484 }
485
486 case ucb::OpenMode::ALL:
487 default:
488 break;
489 }
490
491 m_pImpl->m_aResults.push_back(
492 new ResultListEntry( pContentProperties ) );
493 }
494 }
495 catch ( DAVException const & )
496 {
497 }
498 }
499
500 m_pImpl->m_bCountFinal = sal_True;
501
502 // Callback possible, because listeners may be informed!
503 aGuard.clear();
504 getResultSet()->rowCountFinal();
505 }
506 return !m_pImpl->m_bThrowException;
507 }
508
509