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