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 64 ResultListEntry( const ContentProperties* pEntry ) : pData( pEntry ) {}; 65 ~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 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 ), m_nOpenMode( nOpenMode ), 97 m_bCountFinal( sal_False ), m_bThrowException( sal_False ) {} 98 ~DataSupplier_Impl(); 99 }; 100 101 //========================================================================= 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 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 134 DataSupplier::~DataSupplier() 135 { 136 delete m_pImpl; 137 } 138 139 //========================================================================= 140 // virtual 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 > 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 > 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 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 269 sal_uInt32 DataSupplier::totalCount() 270 { 271 // Obtain values... 272 getData(); 273 274 return m_pImpl->m_aResults.size(); 275 } 276 277 //========================================================================= 278 // virtual 279 sal_uInt32 DataSupplier::currentCount() 280 { 281 return m_pImpl->m_aResults.size(); 282 } 283 284 //========================================================================= 285 // virtual 286 sal_Bool DataSupplier::isCountFinal() 287 { 288 return m_pImpl->m_bCountFinal; 289 } 290 291 //========================================================================= 292 // virtual 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 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 337 void DataSupplier::close() 338 { 339 } 340 341 //========================================================================= 342 // virtual 343 void DataSupplier::validate() 344 throw( ucb::ResultSetException ) 345 { 346 if ( m_pImpl->m_bThrowException ) 347 throw ucb::ResultSetException(); 348 } 349 350 //========================================================================= 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