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