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_ucbhelper.hxx" 26 27 /************************************************************************** 28 TODO 29 ************************************************************************** 30 31 *************************************************************************/ 32 33 #include <hash_map> 34 #include <com/sun/star/beans/XPropertyAccess.hpp> 35 #include <com/sun/star/container/XNameAccess.hpp> 36 #include <com/sun/star/container/XNamed.hpp> 37 #include <com/sun/star/ucb/XPropertySetRegistryFactory.hpp> 38 #include <com/sun/star/ucb/XPropertySetRegistry.hpp> 39 40 #include "osl/diagnose.h" 41 #include "osl/mutex.hxx" 42 #include "cppuhelper/weakref.hxx" 43 #include <ucbhelper/contentidentifier.hxx> 44 #include <ucbhelper/providerhelper.hxx> 45 #include <ucbhelper/contenthelper.hxx> 46 47 using namespace com::sun::star; 48 49 namespace ucbhelper_impl 50 { 51 52 //========================================================================= 53 // 54 // Contents. 55 // 56 //========================================================================= 57 58 struct equalString 59 { 60 bool operator()( 61 const rtl::OUString& rKey11, const rtl::OUString& rKey22 ) const 62 { 63 return !!( rKey11 == rKey22 ); 64 } 65 }; 66 67 struct hashString 68 { 69 size_t operator()( const rtl::OUString & rName ) const 70 { 71 return rName.hashCode(); 72 } 73 }; 74 75 typedef std::hash_map 76 < 77 rtl::OUString, 78 uno::WeakReference< ucb::XContent >, 79 hashString, 80 equalString 81 > 82 Contents; 83 84 //========================================================================= 85 // 86 // struct ContentProviderImplHelper_Impl. 87 // 88 //========================================================================= 89 90 struct ContentProviderImplHelper_Impl 91 { 92 uno::Reference< com::sun::star::ucb::XPropertySetRegistry > 93 m_xPropertySetRegistry; 94 Contents 95 m_aContents; 96 }; 97 98 } // namespace ucbhelper_impl 99 100 //========================================================================= 101 //========================================================================= 102 // 103 // ContentProviderImplHelper Implementation. 104 // 105 //========================================================================= 106 //========================================================================= 107 108 namespace ucbhelper { 109 110 ContentProviderImplHelper::ContentProviderImplHelper( 111 const uno::Reference< lang::XMultiServiceFactory >& rXSMgr ) 112 : m_pImpl( new ucbhelper_impl::ContentProviderImplHelper_Impl ), 113 m_xSMgr( rXSMgr ) 114 { 115 } 116 117 //========================================================================= 118 // virtual 119 ContentProviderImplHelper::~ContentProviderImplHelper() 120 { 121 delete m_pImpl; 122 } 123 124 //========================================================================= 125 // 126 // XInterface methods. 127 // 128 //========================================================================= 129 130 XINTERFACE_IMPL_3( ContentProviderImplHelper, 131 lang::XTypeProvider, 132 lang::XServiceInfo, 133 com::sun::star::ucb::XContentProvider ); 134 135 //========================================================================= 136 // 137 // XTypeProvider methods. 138 // 139 //========================================================================= 140 141 XTYPEPROVIDER_IMPL_3( ContentProviderImplHelper, 142 lang::XTypeProvider, 143 lang::XServiceInfo, 144 com::sun::star::ucb::XContentProvider ); 145 146 //========================================================================= 147 // 148 // XServiceInfo methods. 149 // 150 //========================================================================= 151 152 // virtual 153 sal_Bool SAL_CALL ContentProviderImplHelper::supportsService( 154 const rtl::OUString& ServiceName ) 155 throw( uno::RuntimeException ) 156 { 157 uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames(); 158 const rtl::OUString* pArray = aSNL.getConstArray(); 159 for ( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) 160 { 161 if ( pArray[ i ] == ServiceName ) 162 return sal_True; 163 } 164 165 return sal_False; 166 } 167 168 //========================================================================= 169 // 170 // XContentProvider methods. 171 // 172 //========================================================================= 173 174 // virtual 175 sal_Int32 SAL_CALL ContentProviderImplHelper::compareContentIds( 176 const uno::Reference< com::sun::star::ucb::XContentIdentifier >& Id1, 177 const uno::Reference< com::sun::star::ucb::XContentIdentifier >& Id2 ) 178 throw( uno::RuntimeException ) 179 { 180 // Simply do a string compare. 181 182 rtl::OUString aURL1( Id1->getContentIdentifier() ); 183 rtl::OUString aURL2( Id2->getContentIdentifier() ); 184 185 return aURL1.compareTo( aURL2 );; 186 } 187 188 //========================================================================= 189 // 190 // Non-interface methods 191 // 192 //========================================================================= 193 194 void ContentProviderImplHelper::cleanupRegisteredContents() 195 { 196 osl::MutexGuard aGuard( m_aMutex ); 197 198 ucbhelper_impl::Contents::iterator it 199 = m_pImpl->m_aContents.begin(); 200 while( it != m_pImpl->m_aContents.end() ) 201 { 202 uno::Reference< ucb::XContent > xContent( (*it).second ); 203 if ( !xContent.is() ) 204 { 205 ucbhelper_impl::Contents::iterator tmp = it; 206 ++it; 207 m_pImpl->m_aContents.erase( tmp ); 208 } 209 else 210 { 211 ++it; 212 } 213 } 214 } 215 216 //========================================================================= 217 218 void ContentProviderImplHelper::removeContent( ContentImplHelper* pContent ) 219 { 220 osl::MutexGuard aGuard( m_aMutex ); 221 222 cleanupRegisteredContents(); 223 224 const rtl::OUString aURL( 225 pContent->getIdentifier()->getContentIdentifier() ); 226 227 ucbhelper_impl::Contents::iterator it = m_pImpl->m_aContents.find( aURL ); 228 229 if ( it != m_pImpl->m_aContents.end() ) 230 m_pImpl->m_aContents.erase( it ); 231 } 232 233 //========================================================================= 234 rtl::Reference< ContentImplHelper > 235 ContentProviderImplHelper::queryExistingContent( 236 const uno::Reference< com::sun::star::ucb::XContentIdentifier >& 237 Identifier ) 238 { 239 return queryExistingContent( Identifier->getContentIdentifier() ); 240 } 241 242 //========================================================================= 243 rtl::Reference< ContentImplHelper > 244 ContentProviderImplHelper::queryExistingContent( const rtl::OUString& rURL ) 245 { 246 osl::MutexGuard aGuard( m_aMutex ); 247 248 cleanupRegisteredContents(); 249 250 // Check, if a content with given id already exists... 251 252 ucbhelper_impl::Contents::const_iterator it 253 = m_pImpl->m_aContents.find( rURL ); 254 if ( it != m_pImpl->m_aContents.end() ) 255 { 256 uno::Reference< ucb::XContent > xContent( (*it).second ); 257 if ( xContent.is() ) 258 { 259 return rtl::Reference< ContentImplHelper >( 260 static_cast< ContentImplHelper * >( xContent.get() ) ); 261 } 262 } 263 return rtl::Reference< ContentImplHelper >(); 264 } 265 266 //========================================================================= 267 void ContentProviderImplHelper::queryExistingContents( 268 ContentRefList& rContents ) 269 { 270 osl::MutexGuard aGuard( m_aMutex ); 271 272 cleanupRegisteredContents(); 273 274 ucbhelper_impl::Contents::const_iterator it 275 = m_pImpl->m_aContents.begin(); 276 ucbhelper_impl::Contents::const_iterator end 277 = m_pImpl->m_aContents.end(); 278 279 while ( it != end ) 280 { 281 uno::Reference< ucb::XContent > xContent( (*it).second ); 282 if ( xContent.is() ) 283 { 284 rContents.push_back( 285 rtl::Reference< ContentImplHelper >( 286 static_cast< ContentImplHelper * >( xContent.get() ) ) ); 287 } 288 ++it; 289 } 290 } 291 292 //========================================================================= 293 void ContentProviderImplHelper::registerNewContent( 294 const uno::Reference< ucb::XContent > & xContent ) 295 { 296 if ( xContent.is() ) 297 { 298 osl::MutexGuard aGuard( m_aMutex ); 299 300 cleanupRegisteredContents(); 301 302 const rtl::OUString aURL( 303 xContent->getIdentifier()->getContentIdentifier() ); 304 ucbhelper_impl::Contents::const_iterator it 305 = m_pImpl->m_aContents.find( aURL ); 306 if ( it == m_pImpl->m_aContents.end() ) 307 m_pImpl->m_aContents[ aURL ] = xContent; 308 } 309 } 310 311 //========================================================================= 312 uno::Reference< com::sun::star::ucb::XPropertySetRegistry > 313 ContentProviderImplHelper::getAdditionalPropertySetRegistry() 314 { 315 // Get propertyset registry. 316 317 osl::MutexGuard aGuard( m_aMutex ); 318 319 if ( !m_pImpl->m_xPropertySetRegistry.is() ) 320 { 321 uno::Reference< com::sun::star::ucb::XPropertySetRegistryFactory > 322 xRegFac( 323 m_xSMgr->createInstance( 324 rtl::OUString::createFromAscii( 325 "com.sun.star.ucb.Store" ) ), 326 uno::UNO_QUERY ); 327 328 OSL_ENSURE( xRegFac.is(), 329 "ContentProviderImplHelper::getAdditionalPropertySet - " 330 "No UCB-Store service!" ); 331 332 if ( xRegFac.is() ) 333 { 334 // Open/create a registry. 335 m_pImpl->m_xPropertySetRegistry 336 = xRegFac->createPropertySetRegistry( rtl::OUString() ); 337 338 OSL_ENSURE( m_pImpl->m_xPropertySetRegistry.is(), 339 "ContentProviderImplHelper::getAdditionalPropertySet - " 340 "Error opening registry!" ); 341 } 342 } 343 344 return m_pImpl->m_xPropertySetRegistry; 345 } 346 347 348 //========================================================================= 349 uno::Reference< com::sun::star::ucb::XPersistentPropertySet > 350 ContentProviderImplHelper::getAdditionalPropertySet( 351 const rtl::OUString& rKey, sal_Bool bCreate ) 352 { 353 // Get propertyset registry. 354 getAdditionalPropertySetRegistry(); 355 356 if ( m_pImpl->m_xPropertySetRegistry.is() ) 357 { 358 // Open/create persistent property set. 359 return uno::Reference< com::sun::star::ucb::XPersistentPropertySet >( 360 m_pImpl->m_xPropertySetRegistry->openPropertySet( 361 rKey, bCreate ) ); 362 } 363 364 return uno::Reference< com::sun::star::ucb::XPersistentPropertySet >(); 365 } 366 367 //========================================================================= 368 sal_Bool ContentProviderImplHelper::renameAdditionalPropertySet( 369 const rtl::OUString& rOldKey, 370 const rtl::OUString& rNewKey, 371 sal_Bool bRecursive ) 372 { 373 if ( rOldKey == rNewKey ) 374 return sal_True; 375 376 osl::MutexGuard aGuard( m_aMutex ); 377 378 if ( bRecursive ) 379 { 380 // Get propertyset registry. 381 getAdditionalPropertySetRegistry(); 382 383 if ( m_pImpl->m_xPropertySetRegistry.is() ) 384 { 385 uno::Reference< container::XNameAccess > xNameAccess( 386 m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY ); 387 if ( xNameAccess.is() ) 388 { 389 uno::Sequence< rtl::OUString > aKeys 390 = xNameAccess->getElementNames(); 391 sal_Int32 nCount = aKeys.getLength(); 392 if ( nCount > 0 ) 393 { 394 rtl::OUString aOldKeyWithSlash = rOldKey; 395 rtl::OUString aOldKeyWithoutSlash; 396 if ( aOldKeyWithSlash.lastIndexOf( 397 sal_Unicode('/') 398 != aOldKeyWithSlash.getLength() - 1 ) ) 399 { 400 aOldKeyWithSlash += rtl::OUString( sal_Unicode('/') ); 401 aOldKeyWithoutSlash = rOldKey; 402 } 403 else if ( rOldKey.getLength() ) 404 aOldKeyWithoutSlash 405 = rOldKey.copy( 0, rOldKey.getLength() - 1 ); 406 407 const rtl::OUString* pKeys = aKeys.getConstArray(); 408 for ( sal_Int32 n = 0; n < nCount; ++n ) 409 { 410 const rtl::OUString& rKey = pKeys[ n ]; 411 if ( rKey.compareTo( 412 aOldKeyWithSlash, 413 aOldKeyWithSlash.getLength() ) == 0 414 || rKey.equals( aOldKeyWithoutSlash ) ) 415 { 416 rtl::OUString aNewKey 417 = rKey.replaceAt( 418 0, rOldKey.getLength(), rNewKey ); 419 if ( !renameAdditionalPropertySet( 420 rKey, aNewKey, sal_False ) ) 421 return sal_False; 422 } 423 } 424 } 425 } 426 else 427 return sal_False; 428 } 429 else 430 return sal_False; 431 } 432 else 433 { 434 // Get old property set, if exists. 435 uno::Reference< com::sun::star::ucb::XPersistentPropertySet > xOldSet 436 = getAdditionalPropertySet( rOldKey, sal_False ); 437 if ( xOldSet.is() ) 438 { 439 // Rename property set. 440 uno::Reference< container::XNamed > xNamed( 441 xOldSet, uno::UNO_QUERY ); 442 if ( xNamed.is() ) 443 { 444 // ??? throws no exceptions and has no return value ??? 445 xNamed->setName( rNewKey ); 446 } 447 else 448 return sal_False; 449 } 450 } 451 return sal_True; 452 } 453 454 //========================================================================= 455 sal_Bool ContentProviderImplHelper::copyAdditionalPropertySet( 456 const rtl::OUString& rSourceKey, 457 const rtl::OUString& rTargetKey, 458 sal_Bool bRecursive ) 459 { 460 if ( rSourceKey == rTargetKey ) 461 return sal_True; 462 463 osl::MutexGuard aGuard( m_aMutex ); 464 465 if ( bRecursive ) 466 { 467 // Get propertyset registry. 468 getAdditionalPropertySetRegistry(); 469 470 if ( m_pImpl->m_xPropertySetRegistry.is() ) 471 { 472 uno::Reference< container::XNameAccess > xNameAccess( 473 m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY ); 474 if ( xNameAccess.is() ) 475 { 476 uno::Sequence< rtl::OUString > aKeys 477 = xNameAccess->getElementNames(); 478 sal_Int32 nCount = aKeys.getLength(); 479 if ( nCount > 0 ) 480 { 481 rtl::OUString aSrcKeyWithSlash = rSourceKey; 482 rtl::OUString aSrcKeyWithoutSlash; 483 if ( aSrcKeyWithSlash.lastIndexOf( 484 sal_Unicode('/') 485 != aSrcKeyWithSlash.getLength() - 1 ) ) 486 { 487 aSrcKeyWithSlash += rtl::OUString( sal_Unicode('/') ); 488 aSrcKeyWithoutSlash = rSourceKey; 489 } 490 else if ( rSourceKey.getLength() ) 491 aSrcKeyWithoutSlash = rSourceKey.copy( 492 0, rSourceKey.getLength() - 1 ); 493 494 const rtl::OUString* pKeys = aKeys.getConstArray(); 495 for ( sal_Int32 n = 0; n < nCount; ++n ) 496 { 497 const rtl::OUString& rKey = pKeys[ n ]; 498 if ( rKey.compareTo( 499 aSrcKeyWithSlash, 500 aSrcKeyWithSlash.getLength() ) == 0 501 || rKey.equals( aSrcKeyWithoutSlash ) ) 502 { 503 rtl::OUString aNewKey 504 = rKey.replaceAt( 505 0, rSourceKey.getLength(), rTargetKey ); 506 if ( !copyAdditionalPropertySet( 507 rKey, aNewKey, sal_False ) ) 508 return sal_False; 509 } 510 } 511 } 512 } 513 else 514 return sal_False; 515 } 516 else 517 return sal_False; 518 } 519 else 520 { 521 // Get old property set, if exists. 522 uno::Reference< com::sun::star::ucb::XPersistentPropertySet > 523 xOldPropSet = getAdditionalPropertySet( rSourceKey, sal_False ); 524 if ( !xOldPropSet.is() ) 525 return sal_False; 526 527 uno::Reference< beans::XPropertySetInfo > xPropSetInfo 528 = xOldPropSet->getPropertySetInfo(); 529 if ( !xPropSetInfo.is() ) 530 return sal_False; 531 532 uno::Reference< beans::XPropertyAccess > xOldPropAccess( 533 xOldPropSet, uno::UNO_QUERY ); 534 if ( !xOldPropAccess.is() ) 535 return sal_False; 536 537 // Obtain all values from old set. 538 uno::Sequence< beans::PropertyValue > aValues 539 = xOldPropAccess->getPropertyValues(); 540 sal_Int32 nCount = aValues.getLength(); 541 542 uno::Sequence< beans::Property > aProps 543 = xPropSetInfo->getProperties(); 544 545 if ( nCount ) 546 { 547 // Fail, if property set with new key already exists. 548 uno::Reference< com::sun::star::ucb::XPersistentPropertySet > 549 xNewPropSet 550 = getAdditionalPropertySet( rTargetKey, sal_False ); 551 if ( xNewPropSet.is() ) 552 return sal_False; 553 554 // Create new, empty set. 555 xNewPropSet = getAdditionalPropertySet( rTargetKey, sal_True ); 556 if ( !xNewPropSet.is() ) 557 return sal_False; 558 559 uno::Reference< beans::XPropertyContainer > xNewPropContainer( 560 xNewPropSet, uno::UNO_QUERY ); 561 if ( !xNewPropContainer.is() ) 562 return sal_False; 563 564 for ( sal_Int32 n = 0; n < nCount; ++n ) 565 { 566 const beans::PropertyValue& rValue = aValues[ n ]; 567 568 sal_Int16 nAttribs = 0; 569 for ( sal_Int32 m = 0; m < aProps.getLength(); ++m ) 570 { 571 if ( aProps[ m ].Name == rValue.Name ) 572 { 573 nAttribs = aProps[ m ].Attributes; 574 break; 575 } 576 } 577 578 try 579 { 580 xNewPropContainer->addProperty( 581 rValue.Name, nAttribs, rValue.Value ); 582 } 583 catch ( beans::PropertyExistException & ) 584 { 585 } 586 catch ( beans::IllegalTypeException & ) 587 { 588 } 589 catch ( lang::IllegalArgumentException & ) 590 { 591 } 592 } 593 } 594 } 595 return sal_True; 596 } 597 598 //========================================================================= 599 sal_Bool ContentProviderImplHelper::removeAdditionalPropertySet( 600 const rtl::OUString& rKey, sal_Bool bRecursive ) 601 { 602 osl::MutexGuard aGuard( m_aMutex ); 603 604 if ( bRecursive ) 605 { 606 // Get propertyset registry. 607 getAdditionalPropertySetRegistry(); 608 609 if ( m_pImpl->m_xPropertySetRegistry.is() ) 610 { 611 uno::Reference< container::XNameAccess > xNameAccess( 612 m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY ); 613 if ( xNameAccess.is() ) 614 { 615 uno::Sequence< rtl::OUString > aKeys 616 = xNameAccess->getElementNames(); 617 sal_Int32 nCount = aKeys.getLength(); 618 if ( nCount > 0 ) 619 { 620 rtl::OUString aKeyWithSlash = rKey; 621 rtl::OUString aKeyWithoutSlash; 622 if ( aKeyWithSlash.lastIndexOf( 623 sal_Unicode('/') 624 != aKeyWithSlash.getLength() - 1 ) ) 625 { 626 aKeyWithSlash += rtl::OUString( (sal_Unicode)'/' ); 627 aKeyWithoutSlash = rKey; 628 } 629 else if ( rKey.getLength() ) 630 aKeyWithoutSlash 631 = rKey.copy( 0, rKey.getLength() - 1 ); 632 633 const rtl::OUString* pKeys = aKeys.getConstArray(); 634 for ( sal_Int32 n = 0; n < nCount; ++n ) 635 { 636 const rtl::OUString& rCurrKey = pKeys[ n ]; 637 if ( rCurrKey.compareTo( 638 aKeyWithSlash, 639 aKeyWithSlash.getLength() ) == 0 640 || rCurrKey.equals( aKeyWithoutSlash ) ) 641 { 642 if ( !removeAdditionalPropertySet( 643 rCurrKey, sal_False ) ) 644 return sal_False; 645 } 646 } 647 } 648 } 649 else 650 return sal_False; 651 } 652 else 653 return sal_False; 654 } 655 else 656 { 657 // Get propertyset registry. 658 getAdditionalPropertySetRegistry(); 659 660 if ( m_pImpl->m_xPropertySetRegistry.is() ) 661 m_pImpl->m_xPropertySetRegistry->removePropertySet( rKey ); 662 else 663 return sal_False; 664 } 665 return sal_True; 666 } 667 668 } // namespace ucbhelper 669