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 "osl/diagnose.h" 38 39 #include "com/sun/star/beans/PropertyAttribute.hpp" 40 #include "com/sun/star/beans/XPropertyAccess.hpp" 41 #include "com/sun/star/lang/IllegalAccessException.hpp" 42 #include "com/sun/star/sdbc/XRow.hpp" 43 #include "com/sun/star/ucb/XCommandInfo.hpp" 44 #include "com/sun/star/ucb/XPersistentPropertySet.hpp" 45 #include "ucbhelper/contentidentifier.hxx" 46 #include "ucbhelper/propertyvalueset.hxx" 47 #include "ucbhelper/cancelcommandexecution.hxx" 48 49 #include "myucp_content.hxx" 50 #include "myucp_provider.hxx" 51 52 #ifdef IMPLEMENT_COMMAND_INSERT 53 #include "com/sun/star/ucb/InsertCommandArgument.hpp" 54 #include "com/sun/star/ucb/MissingInputStreamException.hpp" 55 #include "com/sun/star/ucb/MissingPropertiesException.hpp" 56 #endif 57 #ifdef IMPLEMENT_COMMAND_OPEN 58 #include "com/sun/star/io/XOutputStream.hpp" 59 #include "com/sun/star/io/XActiveDataSink.hpp" 60 #include "com/sun/star/ucb/OpenCommandArgument2.hpp" 61 #include "com/sun/star/ucb/OpenMode.hpp" 62 #include "com/sun/star/ucb/UnsupportedDataSinkException.hpp" 63 #include "com/sun/star/ucb/UnsupportedOpenModeException.hpp" 64 #include "myucp_resultset.hxx" 65 #endif 66 67 using namespace com::sun::star; 68 69 // @@@ Adjust namespace name. 70 using namespace myucp; 71 72 //========================================================================= 73 //========================================================================= 74 // 75 // Content Implementation. 76 // 77 //========================================================================= 78 //========================================================================= 79 80 Content::Content( const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 81 ::ucbhelper::ContentProviderImplHelper* pProvider, 82 const uno::Reference< ucb::XContentIdentifier >& Identifier ) 83 : ContentImplHelper( rxSMgr, pProvider, Identifier ) 84 { 85 // @@@ Fill m_aProps here or implement lazy evaluation logic for this. 86 // m_aProps.aTitle = 87 // m_aprops.aContentType = 88 // m_aProps.bIsDocument = 89 // m_aProps.bIsFolder = 90 } 91 92 //========================================================================= 93 // virtual 94 Content::~Content() 95 { 96 } 97 98 //========================================================================= 99 // 100 // XInterface methods. 101 // 102 //========================================================================= 103 104 // virtual 105 void SAL_CALL Content::acquire() 106 throw() 107 { 108 ContentImplHelper::acquire(); 109 } 110 111 //========================================================================= 112 // virtual 113 void SAL_CALL Content::release() 114 throw() 115 { 116 ContentImplHelper::release(); 117 } 118 119 //========================================================================= 120 // virtual 121 uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) 122 throw ( uno::RuntimeException ) 123 { 124 uno::Any aRet; 125 126 // @@@ Add support for additional interfaces. 127 #if 0 128 aRet = cppu::queryInterface( rType, 129 static_cast< yyy::Xxxxxxxxx * >( this ) ); 130 #endif 131 132 return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType ); 133 } 134 135 //========================================================================= 136 // 137 // XTypeProvider methods. 138 // 139 //========================================================================= 140 141 XTYPEPROVIDER_COMMON_IMPL( Content ); 142 143 //========================================================================= 144 // virtual 145 uno::Sequence< uno::Type > SAL_CALL Content::getTypes() 146 throw( uno::RuntimeException ) 147 { 148 // @@@ Add own interfaces. 149 150 static cppu::OTypeCollection* pCollection = 0; 151 152 if ( !pCollection ) 153 { 154 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 155 if ( !pCollection ) 156 { 157 static cppu::OTypeCollection aCollection( 158 CPPU_TYPE_REF( lang::XTypeProvider ), 159 CPPU_TYPE_REF( lang::XServiceInfo ), 160 CPPU_TYPE_REF( lang::XComponent ), 161 CPPU_TYPE_REF( ucb::XContent ), 162 CPPU_TYPE_REF( ucb::XCommandProcessor ), 163 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), 164 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), 165 CPPU_TYPE_REF( beans::XPropertyContainer ), 166 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), 167 CPPU_TYPE_REF( container::XChild ) ); 168 pCollection = &aCollection; 169 } 170 } 171 172 return (*pCollection).getTypes(); 173 } 174 175 //========================================================================= 176 // 177 // XServiceInfo methods. 178 // 179 //========================================================================= 180 181 // virtual 182 rtl::OUString SAL_CALL Content::getImplementationName() 183 throw( uno::RuntimeException ) 184 { 185 // @@@ Adjust implementation name. 186 // Prefix with reversed company domain name. 187 return rtl::OUString::createFromAscii( "com.sun.star.comp.myucp.Content" ); 188 } 189 190 //========================================================================= 191 // virtual 192 uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames() 193 throw( uno::RuntimeException ) 194 { 195 // @@@ Adjust macro name. 196 uno::Sequence< rtl::OUString > aSNS( 1 ); 197 aSNS.getArray()[ 0 ] 198 = rtl::OUString::createFromAscii( MYUCP_CONTENT_SERVICE_NAME ); 199 return aSNS; 200 } 201 202 //========================================================================= 203 // 204 // XContent methods. 205 // 206 //========================================================================= 207 208 // virtual 209 rtl::OUString SAL_CALL Content::getContentType() 210 throw( uno::RuntimeException ) 211 { 212 // @@@ Adjust macro name ( def in myucp_provider.hxx ). 213 return rtl::OUString::createFromAscii( MYUCP_CONTENT_TYPE ); 214 } 215 216 //========================================================================= 217 // 218 // XCommandProcessor methods. 219 // 220 //========================================================================= 221 222 // virtual 223 uno::Any SAL_CALL Content::execute( 224 const ucb::Command& aCommand, 225 sal_Int32 /* CommandId */, 226 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 227 throw( uno::Exception, 228 ucb::CommandAbortedException, 229 uno::RuntimeException ) 230 { 231 uno::Any aRet; 232 233 if ( aCommand.Name.equalsAsciiL( 234 RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) ) 235 { 236 ////////////////////////////////////////////////////////////////// 237 // getPropertyValues 238 ////////////////////////////////////////////////////////////////// 239 240 uno::Sequence< beans::Property > Properties; 241 if ( !( aCommand.Argument >>= Properties ) ) 242 { 243 OSL_ENSURE( sal_False, "Wrong argument type!" ); 244 ::ucbhelper::cancelCommandExecution( 245 uno::makeAny( lang::IllegalArgumentException( 246 rtl::OUString(), 247 static_cast< cppu::OWeakObject * >( this ), 248 -1 ) ), 249 Environment ); 250 // Unreachable 251 } 252 253 aRet <<= getPropertyValues( Properties, Environment ); 254 } 255 else if ( aCommand.Name.equalsAsciiL( 256 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) ) 257 { 258 ////////////////////////////////////////////////////////////////// 259 // setPropertyValues 260 ////////////////////////////////////////////////////////////////// 261 262 uno::Sequence< beans::PropertyValue > aProperties; 263 if ( !( aCommand.Argument >>= aProperties ) ) 264 { 265 OSL_ENSURE( sal_False, "Wrong argument type!" ); 266 ::ucbhelper::cancelCommandExecution( 267 uno::makeAny( lang::IllegalArgumentException( 268 rtl::OUString(), 269 static_cast< cppu::OWeakObject * >( this ), 270 -1 ) ), 271 Environment ); 272 // Unreachable 273 } 274 275 if ( !aProperties.getLength() ) 276 { 277 OSL_ENSURE( sal_False, "No properties!" ); 278 ::ucbhelper::cancelCommandExecution( 279 uno::makeAny( lang::IllegalArgumentException( 280 rtl::OUString(), 281 static_cast< cppu::OWeakObject * >( this ), 282 -1 ) ), 283 Environment ); 284 // Unreachable 285 } 286 287 aRet <<= setPropertyValues( aProperties, Environment ); 288 } 289 else if ( aCommand.Name.equalsAsciiL( 290 RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) ) 291 { 292 ////////////////////////////////////////////////////////////////// 293 // getPropertySetInfo 294 ////////////////////////////////////////////////////////////////// 295 296 // Note: Implemented by base class. 297 aRet <<= getPropertySetInfo( Environment ); 298 } 299 else if ( aCommand.Name.equalsAsciiL( 300 RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) ) 301 { 302 ////////////////////////////////////////////////////////////////// 303 // getCommandInfo 304 ////////////////////////////////////////////////////////////////// 305 306 // Note: Implemented by base class. 307 aRet <<= getCommandInfo( Environment ); 308 } 309 #ifdef IMPLEMENT_COMMAND_OPEN 310 else if ( aCommand.Name.equalsAsciiL( 311 RTL_CONSTASCII_STRINGPARAM( "open" ) ) ) 312 { 313 ucb::OpenCommandArgument2 aOpenCommand; 314 if ( !( aCommand.Argument >>= aOpenCommand ) ) 315 { 316 OSL_ENSURE( sal_False, "Wrong argument type!" ); 317 ::ucbhelper::cancelCommandExecution( 318 uno::makeAny( lang::IllegalArgumentException( 319 rtl::OUString(), 320 static_cast< cppu::OWeakObject * >( this ), 321 -1 ) ), 322 Environment ); 323 // Unreachable 324 } 325 326 sal_Bool bOpenFolder = 327 ( ( aOpenCommand.Mode == ucb::OpenMode::ALL ) || 328 ( aOpenCommand.Mode == ucb::OpenMode::FOLDERS ) || 329 ( aOpenCommand.Mode == ucb::OpenMode::DOCUMENTS ) ); 330 331 if ( bOpenFolder /*&& isFolder( Environment )*/ ) 332 { 333 // open as folder - return result set 334 335 uno::Reference< ucb::XDynamicResultSet > xSet 336 = new DynamicResultSet( m_xSMgr, 337 this, 338 aOpenCommand, 339 Environment ); 340 aRet <<= xSet; 341 } 342 343 if ( aOpenCommand.Sink.is() ) 344 { 345 // Open document - supply document data stream. 346 347 // Check open mode 348 if ( ( aOpenCommand.Mode 349 == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) || 350 ( aOpenCommand.Mode 351 == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) ) 352 { 353 // Unsupported. 354 ::ucbhelper::cancelCommandExecution( 355 uno::makeAny( ucb::UnsupportedOpenModeException( 356 rtl::OUString(), 357 static_cast< cppu::OWeakObject * >( this ), 358 sal_Int16( aOpenCommand.Mode ) ) ), 359 Environment ); 360 // Unreachable 361 } 362 363 364 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 365 uno::Reference< io::XOutputStream > xOut 366 = uno::Reference< io::XOutputStream >( 367 aOpenCommand.Sink, uno::UNO_QUERY ); 368 if ( xOut.is() ) 369 { 370 // @@@ write data into xOut 371 } 372 else 373 { 374 uno::Reference< io::XActiveDataSink > xDataSink( 375 aOpenCommand.Sink, uno::UNO_QUERY ); 376 if ( xDataSink.is() ) 377 { 378 uno::Reference< io::XInputStream > xIn 379 /* @@@ your XInputStream + XSeekable impl. object */; 380 xDataSink->setInputStream( xIn ); 381 } 382 else 383 { 384 // Note: aOpenCommand.Sink may contain an XStream 385 // implementation. Support for this type of 386 // sink is optional... 387 ::ucbhelper::cancelCommandExecution( 388 uno::makeAny( ucb::UnsupportedDataSinkException( 389 rtl::OUString(), 390 static_cast< cppu::OWeakObject * >( this ), 391 aOpenCommand.Sink ) ), 392 Environment ); 393 // Unreachable 394 } 395 } 396 } 397 } 398 #endif // IMPLEMENT_COMMAND_OPEN 399 400 #ifdef IMPLEMENT_COMMAND_INSERT 401 else if ( aCommand.Name.equalsAsciiL( 402 RTL_CONSTASCII_STRINGPARAM( "insert" ) ) ) 403 { 404 ////////////////////////////////////////////////////////////////// 405 // insert 406 ////////////////////////////////////////////////////////////////// 407 408 ucb::InsertCommandArgument arg; 409 if ( !( aCommand.Argument >>= arg ) ) 410 { 411 OSL_ENSURE( sal_False, "Wrong argument type!" ); 412 ::ucbhelper::cancelCommandExecution( 413 uno::makeAny( lang::IllegalArgumentException( 414 rtl::OUString(), 415 static_cast< cppu::OWeakObject * >( this ), 416 -1 ) ), 417 Environment ); 418 // Unreachable 419 } 420 421 insert( arg.Data, arg.ReplaceExisting, Environment ); 422 } 423 #endif // IMPLEMENT_COMMAND_INSERT 424 425 #ifdef IMPLEMENT_COMMAND_DELETE 426 else if ( aCommand.Name.equalsAsciiL( 427 RTL_CONSTASCII_STRINGPARAM( "delete" ) ) ) 428 { 429 ////////////////////////////////////////////////////////////////// 430 // delete 431 ////////////////////////////////////////////////////////////////// 432 433 sal_Bool bDeletePhysical = sal_False; 434 aCommand.Argument >>= bDeletePhysical; 435 destroy( bDeletePhysical ); 436 437 // Remove own and all children's Additional Core Properties. 438 removeAdditionalPropertySet( sal_True ); 439 440 // Remove own and all childrens(!) persistent data. 441 // removeData(); 442 } 443 #endif // IMPLEMENT_COMMAND_DELETE 444 else 445 { 446 ////////////////////////////////////////////////////////////////// 447 // Unsupported command 448 ////////////////////////////////////////////////////////////////// 449 450 OSL_ENSURE( sal_False, "Content::execute - unsupported command!" ); 451 452 ::ucbhelper::cancelCommandExecution( 453 uno::makeAny( ucb::UnsupportedCommandException( 454 rtl::OUString(), 455 static_cast< cppu::OWeakObject * >( this ) ) ), 456 Environment ); 457 // Unreachable 458 } 459 460 return aRet; 461 } 462 463 //========================================================================= 464 // virtual 465 void SAL_CALL Content::abort( sal_Int32 ) 466 throw( uno::RuntimeException ) 467 { 468 // @@@ Implement logic to abort running commands, if this makes 469 // sense for your content. 470 } 471 472 //========================================================================= 473 // 474 // Non-interface methods. 475 // 476 //========================================================================= 477 478 // virtual 479 rtl::OUString Content::getParentURL() 480 { 481 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 482 483 // @@@ Extract URL of parent from aURL and return it... 484 485 return rtl::OUString(); 486 } 487 488 //========================================================================= 489 // static 490 uno::Reference< sdbc::XRow > Content::getPropertyValues( 491 const uno::Reference< lang::XMultiServiceFactory >& rSMgr, 492 const uno::Sequence< beans::Property >& rProperties, 493 const ContentProperties& rData, 494 const rtl::Reference< 495 ::ucbhelper::ContentProviderImplHelper >& rProvider, 496 const rtl::OUString& rContentId ) 497 { 498 // Note: Empty sequence means "get values of all supported properties". 499 500 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow 501 = new ::ucbhelper::PropertyValueSet( rSMgr ); 502 503 sal_Int32 nCount = rProperties.getLength(); 504 if ( nCount ) 505 { 506 uno::Reference< beans::XPropertySet > xAdditionalPropSet; 507 sal_Bool bTriedToGetAdditonalPropSet = sal_False; 508 509 const beans::Property* pProps = rProperties.getConstArray(); 510 for ( sal_Int32 n = 0; n < nCount; ++n ) 511 { 512 const beans::Property& rProp = pProps[ n ]; 513 514 // Process Core properties. 515 516 if ( rProp.Name.equalsAsciiL( 517 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) 518 { 519 xRow->appendString ( rProp, rData.aContentType ); 520 } 521 else if ( rProp.Name.equalsAsciiL( 522 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) 523 { 524 xRow->appendString ( rProp, rData.aTitle ); 525 } 526 else if ( rProp.Name.equalsAsciiL( 527 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) 528 { 529 xRow->appendBoolean( rProp, rData.bIsDocument ); 530 } 531 else if ( rProp.Name.equalsAsciiL( 532 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) 533 { 534 xRow->appendBoolean( rProp, rData.bIsFolder ); 535 } 536 537 // @@@ Process other properties supported directly. 538 #if 0 539 else if ( rProp.Name.equalsAsciiL( 540 RTL_CONSTASCII_STRINGPARAM( "xxxxxx" ) ) ) 541 { 542 } 543 #endif 544 else 545 { 546 // @@@ Note: If your data source supports adding/removing 547 // properties, you should implement the interface 548 // XPropertyContainer by yourself and supply your own 549 // logic here. The base class uses the service 550 // "com.sun.star.ucb.Store" to maintain Additional Core 551 // properties. But using server functionality is preferred! 552 553 // Not a Core Property! Maybe it's an Additional Core Property?! 554 555 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) 556 { 557 xAdditionalPropSet 558 = uno::Reference< beans::XPropertySet >( 559 rProvider->getAdditionalPropertySet( rContentId, 560 sal_False ), 561 uno::UNO_QUERY ); 562 bTriedToGetAdditonalPropSet = sal_True; 563 } 564 565 if ( xAdditionalPropSet.is() ) 566 { 567 if ( !xRow->appendPropertySetValue( 568 xAdditionalPropSet, 569 rProp ) ) 570 { 571 // Append empty entry. 572 xRow->appendVoid( rProp ); 573 } 574 } 575 else 576 { 577 // Append empty entry. 578 xRow->appendVoid( rProp ); 579 } 580 } 581 } 582 } 583 else 584 { 585 // Append all Core Properties. 586 xRow->appendString ( 587 beans::Property( rtl::OUString::createFromAscii( "ContentType" ), 588 -1, 589 getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 590 beans::PropertyAttribute::BOUND 591 | beans::PropertyAttribute::READONLY ), 592 rData.aContentType ); 593 xRow->appendString ( 594 beans::Property( rtl::OUString::createFromAscii( "Title" ), 595 -1, 596 getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 597 beans::PropertyAttribute::BOUND ), 598 rData.aTitle ); 599 xRow->appendBoolean( 600 beans::Property( rtl::OUString::createFromAscii( "IsDocument" ), 601 -1, 602 getCppuBooleanType(), 603 beans::PropertyAttribute::BOUND 604 | beans::PropertyAttribute::READONLY ), 605 rData.bIsDocument ); 606 xRow->appendBoolean( 607 beans::Property( rtl::OUString::createFromAscii( "IsFolder" ), 608 -1, 609 getCppuBooleanType(), 610 beans::PropertyAttribute::BOUND 611 | beans::PropertyAttribute::READONLY ), 612 rData.bIsFolder ); 613 614 // @@@ Append other properties supported directly. 615 616 // @@@ Note: If your data source supports adding/removing 617 // properties, you should implement the interface 618 // XPropertyContainer by yourself and supply your own 619 // logic here. The base class uses the service 620 // "com.sun.star.ucb.Store" to maintain Additional Core 621 // properties. But using server functionality is preferred! 622 623 // Append all Additional Core Properties. 624 625 uno::Reference< beans::XPropertySet > xSet( 626 rProvider->getAdditionalPropertySet( rContentId, sal_False ), 627 uno::UNO_QUERY ); 628 xRow->appendPropertySet( xSet ); 629 } 630 631 return uno::Reference< sdbc::XRow >( xRow.get() ); 632 } 633 634 //========================================================================= 635 uno::Reference< sdbc::XRow > Content::getPropertyValues( 636 const uno::Sequence< beans::Property >& rProperties, 637 const uno::Reference< ucb::XCommandEnvironment >& /* xEnv */) 638 { 639 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 640 return getPropertyValues( m_xSMgr, 641 rProperties, 642 m_aProps, 643 rtl::Reference< 644 ::ucbhelper::ContentProviderImplHelper >( 645 m_xProvider.get() ), 646 m_xIdentifier->getContentIdentifier() ); 647 } 648 649 //========================================================================= 650 uno::Sequence< uno::Any > Content::setPropertyValues( 651 const uno::Sequence< beans::PropertyValue >& rValues, 652 const uno::Reference< ucb::XCommandEnvironment >& /* xEnv */) 653 { 654 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 655 656 uno::Sequence< uno::Any > aRet( rValues.getLength() ); 657 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() ); 658 sal_Int32 nChanged = 0; 659 660 beans::PropertyChangeEvent aEvent; 661 aEvent.Source = static_cast< cppu::OWeakObject * >( this ); 662 aEvent.Further = sal_False; 663 // aEvent.PropertyName = 664 aEvent.PropertyHandle = -1; 665 // aEvent.OldValue = 666 // aEvent.NewValue = 667 668 const beans::PropertyValue* pValues = rValues.getConstArray(); 669 sal_Int32 nCount = rValues.getLength(); 670 671 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet; 672 sal_Bool bTriedToGetAdditonalPropSet = sal_False; 673 674 for ( sal_Int32 n = 0; n < nCount; ++n ) 675 { 676 const beans::PropertyValue& rValue = pValues[ n ]; 677 678 if ( rValue.Name.equalsAsciiL( 679 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) 680 { 681 // Read-only property! 682 aRet[ n ] <<= lang::IllegalAccessException( 683 rtl::OUString::createFromAscii( 684 "Property is read-only!" ), 685 static_cast< cppu::OWeakObject * >( this ) ); 686 } 687 else if ( rValue.Name.equalsAsciiL( 688 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) 689 { 690 // Read-only property! 691 aRet[ n ] <<= lang::IllegalAccessException( 692 rtl::OUString::createFromAscii( 693 "Property is read-only!" ), 694 static_cast< cppu::OWeakObject * >( this ) ); 695 } 696 else if ( rValue.Name.equalsAsciiL( 697 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) 698 { 699 // Read-only property! 700 aRet[ n ] <<= lang::IllegalAccessException( 701 rtl::OUString::createFromAscii( 702 "Property is read-only!" ), 703 static_cast< cppu::OWeakObject * >( this ) ); 704 } 705 else if ( rValue.Name.equalsAsciiL( 706 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) 707 { 708 rtl::OUString aNewValue; 709 if ( rValue.Value >>= aNewValue ) 710 { 711 if ( aNewValue != m_aProps.aTitle ) 712 { 713 aEvent.PropertyName = rValue.Name; 714 aEvent.OldValue = uno::makeAny( m_aProps.aTitle ); 715 aEvent.NewValue = uno::makeAny( aNewValue ); 716 717 aChanges.getArray()[ nChanged ] = aEvent; 718 719 m_aProps.aTitle = aNewValue; 720 nChanged++; 721 } 722 else 723 { 724 // Old value equals new value. No error! 725 } 726 } 727 else 728 { 729 aRet[ n ] <<= beans::IllegalTypeException( 730 rtl::OUString::createFromAscii( 731 "Property value has wrong type!" ), 732 static_cast< cppu::OWeakObject * >( this ) ); 733 } 734 } 735 736 // @@@ Process other properties supported directly. 737 #if 0 738 else if ( rValue.Name.equalsAsciiL( 739 RTL_CONSTASCII_STRINGPARAM( "xxxxxx" ) ) ) 740 { 741 } 742 #endif 743 else 744 { 745 // @@@ Note: If your data source supports adding/removing 746 // properties, you should implement the interface 747 // XPropertyContainer by yourself and supply your own 748 // logic here. The base class uses the service 749 // "com.sun.star.ucb.Store" to maintain Additional Core 750 // properties. But using server functionality is preferred! 751 752 // Not a Core Property! Maybe it's an Additional Core Property?! 753 754 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) 755 { 756 xAdditionalPropSet = getAdditionalPropertySet( sal_False ); 757 bTriedToGetAdditonalPropSet = sal_True; 758 } 759 760 if ( xAdditionalPropSet.is() ) 761 { 762 try 763 { 764 uno::Any aOldValue 765 = xAdditionalPropSet->getPropertyValue( rValue.Name ); 766 if ( aOldValue != rValue.Value ) 767 { 768 xAdditionalPropSet->setPropertyValue( 769 rValue.Name, rValue.Value ); 770 771 aEvent.PropertyName = rValue.Name; 772 aEvent.OldValue = aOldValue; 773 aEvent.NewValue = rValue.Value; 774 775 aChanges.getArray()[ nChanged ] = aEvent; 776 nChanged++; 777 } 778 else 779 { 780 // Old value equals new value. No error! 781 } 782 } 783 catch ( beans::UnknownPropertyException const & e ) 784 { 785 aRet[ n ] <<= e; 786 } 787 catch ( lang::WrappedTargetException const & e ) 788 { 789 aRet[ n ] <<= e; 790 } 791 catch ( beans::PropertyVetoException const & e ) 792 { 793 aRet[ n ] <<= e; 794 } 795 catch ( lang::IllegalArgumentException const & e ) 796 { 797 aRet[ n ] <<= e; 798 } 799 } 800 else 801 { 802 aRet[ n ] <<= uno::Exception( 803 rtl::OUString::createFromAscii( 804 "No property set for storing the value!" ), 805 static_cast< cppu::OWeakObject * >( this ) ); 806 } 807 } 808 } 809 810 if ( nChanged > 0 ) 811 { 812 // @@@ Save changes. 813 // storeData(); 814 815 aGuard.clear(); 816 aChanges.realloc( nChanged ); 817 notifyPropertiesChange( aChanges ); 818 } 819 820 return aRet; 821 } 822 823 #ifdef IMPLEMENT_COMMAND_INSERT 824 825 //========================================================================= 826 void Content::queryChildren( ContentRefList& rChildren ) 827 { 828 // @@@ Adapt method to your URL scheme... 829 830 // Obtain a list with a snapshot of all currently instanciated contents 831 // from provider and extract the contents which are direct children 832 // of this content. 833 834 ::ucbhelper::ContentRefList aAllContents; 835 m_xProvider->queryExistingContents( aAllContents ); 836 837 ::rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 838 sal_Int32 nPos = aURL.lastIndexOf( '/' ); 839 840 if ( nPos != ( aURL.getLength() - 1 ) ) 841 { 842 // No trailing slash found. Append. 843 aURL += ::rtl::OUString::createFromAscii( "/" ); 844 } 845 846 sal_Int32 nLen = aURL.getLength(); 847 848 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); 849 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); 850 851 while ( it != end ) 852 { 853 ::ucbhelper::ContentImplHelperRef xChild = (*it); 854 ::rtl::OUString aChildURL 855 = xChild->getIdentifier()->getContentIdentifier(); 856 857 // Is aURL a prefix of aChildURL? 858 if ( ( aChildURL.getLength() > nLen ) && 859 ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) 860 { 861 nPos = aChildURL.indexOf( '/', nLen ); 862 863 if ( ( nPos == -1 ) || 864 ( nPos == ( aChildURL.getLength() - 1 ) ) ) 865 { 866 // No further slashes / only a final slash. It's a child! 867 rChildren.push_back( 868 ContentRef( 869 static_cast< Content * >( xChild.get() ) ) ); 870 } 871 } 872 ++it; 873 } 874 } 875 876 //========================================================================= 877 void Content::insert( 878 const uno::Reference< io::XInputStream > & xInputStream, 879 sal_Bool bReplaceExisting, 880 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 881 throw( uno::Exception ) 882 { 883 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 884 885 // Check, if all required properties were set. 886 887 #if 0 888 // @@@ add checks for property presence 889 if ( m_aProps.xxxx == yyyyy ) 890 { 891 OSL_ENSURE( sal_False, "Content::insert - property value missing!" ); 892 893 uno::Sequence< rtl::OUString > aProps( 1 ); 894 aProps[ 0 ] = rtl::OUString::createFromAscii( "zzzz" ); 895 ::ucbhelper::cancelCommandExecution( 896 uno::makeAny( ucb::MissingPropertiesException( 897 rtl::OUString(), 898 static_cast< cppu::OWeakObject * >( this ), 899 aProps ) ), 900 Environment ); 901 // Unreachable 902 } 903 #endif 904 905 bool bNeedInputStream = true; // @@@ adjust to real requirements 906 if ( bNeedInputStream && !xInputStream.is() ) 907 { 908 OSL_ENSURE( sal_False, "Content::insert - No data stream!" ); 909 910 ::ucbhelper::cancelCommandExecution( 911 uno::makeAny( ucb::MissingInputStreamException( 912 rtl::OUString(), 913 static_cast< cppu::OWeakObject * >( this ) ) ), 914 Environment ); 915 // Unreachable 916 } 917 918 // Assemble new content identifier... 919 920 uno::Reference< ucb::XContentIdentifier > xId /* @@@ create content identifier */; 921 922 // Fail, if a resource with given id already exists. 923 if ( !bReplaceExisting /*&& hasData( xId ) @@@ impl for hasData() */ ) 924 { 925 uno::Any aProps 926 = uno::makeAny( beans::PropertyValue( 927 rtl::OUString( 928 RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ), 929 -1, 930 uno::makeAny( xId->getContentIdentifier() ), 931 beans::PropertyState_DIRECT_VALUE ) ); 932 ucbhelper::cancelCommandExecution( 933 ucb::IOErrorCode_ALREADY_EXISTING, 934 uno::Sequence< uno::Any >(&aProps, 1), 935 Environment, 936 rtl::OUString::createFromAscii( "content already existing!!" ), 937 this ); 938 // Unreachable 939 } 940 941 m_xIdentifier = xId; 942 943 // @@@ 944 // storeData(); 945 946 aGuard.clear(); 947 inserted(); 948 } 949 950 #endif // IMPLEMENT_COMMAND_INSERT 951 952 #ifdef IMPLEMENT_COMMAND_DELETE 953 954 //========================================================================= 955 void Content::destroy( sal_Bool bDeletePhysical ) 956 throw( uno::Exception ) 957 { 958 // @@@ take care about bDeletePhysical -> trashcan support 959 960 uno::Reference< ucb::XContent > xThis = this; 961 962 deleted(); 963 964 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 965 966 // Process instanciated children... 967 968 ContentRefList aChildren; 969 queryChildren( aChildren ); 970 971 ContentRefList::const_iterator it = aChildren.begin(); 972 ContentRefList::const_iterator end = aChildren.end(); 973 974 while ( it != end ) 975 { 976 (*it)->destroy( bDeletePhysical ); 977 ++it; 978 } 979 } 980 981 #endif // IMPLEMENT_COMMAND_DELETE 982 983 984