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