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 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_file.hxx" 24 #include <rtl/uri.hxx> 25 #include <rtl/ustrbuf.hxx> 26 #include <osl/file.hxx> 27 28 #include "osl/diagnose.h" 29 #include <com/sun/star/ucb/OpenMode.hpp> 30 #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBBUTE_HPP_ 31 #include <com/sun/star/beans/PropertyAttribute.hpp> 32 #endif 33 #include <com/sun/star/ucb/XProgressHandler.hpp> 34 #include <com/sun/star/task/XInteractionHandler.hpp> 35 #include <com/sun/star/io/XActiveDataStreamer.hpp> 36 #include <com/sun/star/io/XOutputStream.hpp> 37 #include <com/sun/star/ucb/NumberedSortingInfo.hpp> 38 #include <com/sun/star/io/XActiveDataSink.hpp> 39 #include <com/sun/star/beans/PropertyChangeEvent.hpp> 40 #include <com/sun/star/beans/PropertySetInfoChange.hpp> 41 #include <com/sun/star/ucb/ContentAction.hpp> 42 #include <com/sun/star/ucb/NameClash.hpp> 43 #include "filglob.hxx" 44 #include "filid.hxx" 45 #include "filrow.hxx" 46 #include "bc.hxx" 47 #include "prov.hxx" 48 #ifndef _FILERROR_HXX_ 49 #include "filerror.hxx" 50 #endif 51 #include "filinsreq.hxx" 52 53 54 using namespace fileaccess; 55 using namespace com::sun::star; 56 using namespace com::sun::star::uno; 57 using namespace com::sun::star::ucb; 58 59 // PropertyListeners 60 61 62 typedef cppu::OMultiTypeInterfaceContainerHelperVar< rtl::OUString,hashOUString,equalOUString > 63 PropertyListeners_impl; 64 65 class fileaccess::PropertyListeners 66 : public PropertyListeners_impl 67 { 68 public: 69 PropertyListeners( ::osl::Mutex& aMutex ) 70 : PropertyListeners_impl( aMutex ) 71 { 72 } 73 }; 74 75 76 /****************************************************************************************/ 77 /* BaseContent */ 78 /****************************************************************************************/ 79 80 //////////////////////////////////////////////////////////////////////////////// 81 // Private Constructor for just inserted Contents 82 83 BaseContent::BaseContent( shell* pMyShell, 84 const rtl::OUString& parentName, 85 sal_Bool bFolder ) 86 : m_pMyShell( pMyShell ), 87 m_xContentIdentifier( 0 ), 88 m_aUncPath( parentName ), 89 m_bFolder( bFolder ), 90 m_nState( JustInserted ), 91 m_pDisposeEventListeners( 0 ), 92 m_pContentEventListeners( 0 ), 93 m_pPropertySetInfoChangeListeners( 0 ), 94 m_pPropertyListener( 0 ) 95 { 96 m_pMyShell->m_pProvider->acquire(); 97 // No registering, since we have no name 98 } 99 100 101 //////////////////////////////////////////////////////////////////////////////// 102 // Constructor for full featured Contents 103 104 BaseContent::BaseContent( shell* pMyShell, 105 const Reference< XContentIdentifier >& xContentIdentifier, 106 const rtl::OUString& aUncPath ) 107 : m_pMyShell( pMyShell ), 108 m_xContentIdentifier( xContentIdentifier ), 109 m_aUncPath( aUncPath ), 110 m_bFolder( false ), 111 m_nState( FullFeatured ), 112 m_pDisposeEventListeners( 0 ), 113 m_pContentEventListeners( 0 ), 114 m_pPropertySetInfoChangeListeners( 0 ), 115 m_pPropertyListener( 0 ) 116 { 117 m_pMyShell->m_pProvider->acquire(); 118 m_pMyShell->registerNotifier( m_aUncPath,this ); 119 m_pMyShell->insertDefaultProperties( m_aUncPath ); 120 } 121 122 123 BaseContent::~BaseContent( ) 124 { 125 if( ( m_nState & FullFeatured ) || ( m_nState & Deleted ) ) 126 { 127 m_pMyShell->deregisterNotifier( m_aUncPath,this ); 128 } 129 m_pMyShell->m_pProvider->release(); 130 131 delete m_pDisposeEventListeners; 132 delete m_pContentEventListeners; 133 delete m_pPropertyListener; 134 delete m_pPropertySetInfoChangeListeners; 135 } 136 137 138 ////////////////////////////////////////////////////////////////////////// 139 // XInterface 140 ////////////////////////////////////////////////////////////////////////// 141 142 void SAL_CALL 143 BaseContent::acquire( void ) 144 throw() 145 { 146 OWeakObject::acquire(); 147 } 148 149 150 void SAL_CALL 151 BaseContent::release( void ) 152 throw() 153 { 154 OWeakObject::release(); 155 } 156 157 158 Any SAL_CALL 159 BaseContent::queryInterface( const Type& rType ) 160 { 161 Any aRet = cppu::queryInterface( rType, 162 SAL_STATIC_CAST( lang::XComponent*, this ), 163 SAL_STATIC_CAST( lang::XTypeProvider*, this ), 164 SAL_STATIC_CAST( lang::XServiceInfo*, this ), 165 SAL_STATIC_CAST( XCommandProcessor*, this ), 166 SAL_STATIC_CAST( container::XChild*, this ), 167 SAL_STATIC_CAST( beans::XPropertiesChangeNotifier*, this ), 168 SAL_STATIC_CAST( beans::XPropertyContainer*, this ), 169 SAL_STATIC_CAST( XContentCreator*,this ), 170 SAL_STATIC_CAST( beans::XPropertySetInfoChangeNotifier*, this ), 171 SAL_STATIC_CAST( XContent*,this) ); 172 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); 173 } 174 175 176 177 178 ////////////////////////////////////////////////////////////////////////////////////////// 179 // XComponent 180 //////////////////////////////////////////////////////////////////////////////////////// 181 182 void SAL_CALL 183 BaseContent::addEventListener( const Reference< lang::XEventListener >& Listener ) 184 { 185 osl::MutexGuard aGuard( m_aMutex ); 186 187 if ( ! m_pDisposeEventListeners ) 188 m_pDisposeEventListeners = 189 new cppu::OInterfaceContainerHelper( m_aEventListenerMutex ); 190 191 m_pDisposeEventListeners->addInterface( Listener ); 192 } 193 194 195 void SAL_CALL 196 BaseContent::removeEventListener( const Reference< lang::XEventListener >& Listener ) 197 { 198 osl::MutexGuard aGuard( m_aMutex ); 199 200 if ( m_pDisposeEventListeners ) 201 m_pDisposeEventListeners->removeInterface( Listener ); 202 } 203 204 205 void SAL_CALL 206 BaseContent::dispose() 207 { 208 lang::EventObject aEvt; 209 cppu::OInterfaceContainerHelper* pDisposeEventListeners; 210 cppu::OInterfaceContainerHelper* pContentEventListeners; 211 cppu::OInterfaceContainerHelper* pPropertySetInfoChangeListeners; 212 PropertyListeners* pPropertyListener; 213 214 { 215 osl::MutexGuard aGuard( m_aMutex ); 216 aEvt.Source = static_cast< XContent* >( this ); 217 218 219 pDisposeEventListeners = 220 m_pDisposeEventListeners, m_pDisposeEventListeners = 0; 221 222 pContentEventListeners = 223 m_pContentEventListeners, m_pContentEventListeners = 0; 224 225 pPropertySetInfoChangeListeners = 226 m_pPropertySetInfoChangeListeners, 227 m_pPropertySetInfoChangeListeners = 0; 228 229 pPropertyListener = 230 m_pPropertyListener, m_pPropertyListener = 0; 231 } 232 233 if ( pDisposeEventListeners && pDisposeEventListeners->getLength() ) 234 pDisposeEventListeners->disposeAndClear( aEvt ); 235 236 if ( pContentEventListeners && pContentEventListeners->getLength() ) 237 pContentEventListeners->disposeAndClear( aEvt ); 238 239 if( pPropertyListener ) 240 pPropertyListener->disposeAndClear( aEvt ); 241 242 if( pPropertySetInfoChangeListeners ) 243 pPropertySetInfoChangeListeners->disposeAndClear( aEvt ); 244 245 delete pDisposeEventListeners; 246 delete pContentEventListeners; 247 delete pPropertyListener; 248 delete pPropertySetInfoChangeListeners; 249 } 250 251 252 253 ////////////////////////////////////////////////////////////////////////////////////////// 254 // XServiceInfo 255 ////////////////////////////////////////////////////////////////////////////////////////// 256 257 rtl::OUString SAL_CALL 258 BaseContent::getImplementationName() 259 { 260 return rtl::OUString::createFromAscii( "com.sun.star.comp.ucb.FileContent" ); 261 } 262 263 264 265 sal_Bool SAL_CALL 266 BaseContent::supportsService( const rtl::OUString& ServiceName ) 267 { 268 if( ServiceName.compareToAscii( "com.sun.star.ucb.FileContent" ) == 0 ) 269 return true; 270 else 271 return false; 272 } 273 274 275 276 Sequence< rtl::OUString > SAL_CALL 277 BaseContent::getSupportedServiceNames() 278 { 279 Sequence< rtl::OUString > ret( 1 ); 280 ret[0] = rtl::OUString::createFromAscii( "com.sun.star.ucb.FileContent" ); 281 return ret; 282 } 283 284 285 286 ////////////////////////////////////////////////////////////////////////////////////////// 287 // XTypeProvider 288 ////////////////////////////////////////////////////////////////////////////////////////// 289 290 XTYPEPROVIDER_IMPL_10( BaseContent, 291 lang::XComponent, 292 lang::XTypeProvider, 293 lang::XServiceInfo, 294 XCommandProcessor, 295 XContentCreator, 296 XContent, 297 container::XChild, 298 beans::XPropertiesChangeNotifier, 299 beans::XPropertyContainer, 300 beans::XPropertySetInfoChangeNotifier ) 301 302 303 ////////////////////////////////////////////////////////////////////////////////////////// 304 // XCommandProcessor 305 ////////////////////////////////////////////////////////////////////////////////////////// 306 307 sal_Int32 SAL_CALL 308 BaseContent::createCommandIdentifier( void ) 309 { 310 return m_pMyShell->getCommandId(); 311 } 312 313 314 void SAL_CALL 315 BaseContent::abort( sal_Int32 CommandId ) 316 { 317 m_pMyShell->abort( CommandId ); 318 } 319 320 321 Any SAL_CALL 322 BaseContent::execute( const Command& aCommand, 323 sal_Int32 CommandId, 324 const Reference< XCommandEnvironment >& Environment ) 325 { 326 if( ! CommandId ) 327 // A Command with commandid zero cannot be aborted 328 CommandId = createCommandIdentifier(); 329 330 m_pMyShell->startTask( CommandId, 331 Environment ); 332 333 Any aAny; 334 335 if( ! aCommand.Name.compareToAscii( "getPropertySetInfo" ) ) // No exceptions 336 { 337 aAny <<= getPropertySetInfo( CommandId ); 338 } 339 else if( ! aCommand.Name.compareToAscii( "getCommandInfo" ) ) // no exceptions 340 { 341 aAny <<= getCommandInfo(); 342 } 343 else if( ! aCommand.Name.compareToAscii( "setPropertyValues" ) ) 344 { 345 Sequence< beans::PropertyValue > sPropertyValues; 346 347 if( ! ( aCommand.Argument >>= sPropertyValues ) ) 348 m_pMyShell->installError( CommandId, 349 TASKHANDLING_WRONG_SETPROPERTYVALUES_ARGUMENT ); 350 else 351 aAny <<= setPropertyValues( CommandId,sPropertyValues ); // calls endTask by itself 352 } 353 else if( ! aCommand.Name.compareToAscii( "getPropertyValues" ) ) 354 { 355 Sequence< beans::Property > ListOfRequestedProperties; 356 357 if( ! ( aCommand.Argument >>= ListOfRequestedProperties ) ) 358 m_pMyShell->installError( CommandId, 359 TASKHANDLING_WRONG_GETPROPERTYVALUES_ARGUMENT ); 360 else 361 aAny <<= getPropertyValues( CommandId, 362 ListOfRequestedProperties ); 363 } 364 else if( ! aCommand.Name.compareToAscii( "open" ) ) 365 { 366 OpenCommandArgument2 aOpenArgument; 367 if( ! ( aCommand.Argument >>= aOpenArgument ) ) 368 m_pMyShell->installError( CommandId, 369 TASKHANDLING_WRONG_OPEN_ARGUMENT ); 370 else 371 { 372 Reference< XDynamicResultSet > result = open( CommandId,aOpenArgument ); 373 if( result.is() ) 374 aAny <<= result; 375 } 376 } 377 else if( ! aCommand.Name.compareToAscii( "delete" ) ) 378 { 379 if( ! aCommand.Argument.has< sal_Bool >() ) 380 m_pMyShell->installError( CommandId, 381 TASKHANDLING_WRONG_DELETE_ARGUMENT ); 382 else 383 deleteContent( CommandId ); 384 } 385 else if( ! aCommand.Name.compareToAscii( "transfer" ) ) 386 { 387 TransferInfo aTransferInfo; 388 if( ! ( aCommand.Argument >>= aTransferInfo ) ) 389 m_pMyShell->installError( CommandId, 390 TASKHANDLING_WRONG_TRANSFER_ARGUMENT ); 391 else 392 transfer( CommandId, aTransferInfo ); 393 } 394 else if( ! aCommand.Name.compareToAscii( "insert" ) ) 395 { 396 InsertCommandArgument aInsertArgument; 397 if( ! ( aCommand.Argument >>= aInsertArgument ) ) 398 m_pMyShell->installError( CommandId, 399 TASKHANDLING_WRONG_INSERT_ARGUMENT ); 400 else 401 insert( CommandId,aInsertArgument ); 402 } 403 else if( ! aCommand.Name.compareToAscii( "getCasePreservingURL" ) ) 404 { 405 Sequence< beans::Property > seq(1); 406 seq[0] = beans::Property( 407 rtl::OUString::createFromAscii("CasePreservingURL"), 408 -1, 409 getCppuType( static_cast< sal_Bool* >(0) ), 410 0 ); 411 Reference< sdbc::XRow > xRow = getPropertyValues( CommandId,seq ); 412 rtl::OUString CasePreservingURL = xRow->getString(1); 413 if(!xRow->wasNull()) 414 aAny <<= CasePreservingURL; 415 } 416 else if( ! aCommand.Name.compareToAscii( "createNewContent" ) ) 417 { 418 ucb::ContentInfo aArg; 419 if ( !( aCommand.Argument >>= aArg ) ) 420 m_pMyShell->installError( CommandId, 421 TASKHANDLING_WRONG_CREATENEWCONTENT_ARGUMENT ); 422 else 423 aAny <<= createNewContent( aArg ); 424 } 425 else 426 m_pMyShell->installError( CommandId, 427 TASKHANDLER_UNSUPPORTED_COMMAND ); 428 429 430 // This is the only function allowed to throw an exception 431 endTask( CommandId ); 432 433 return aAny; 434 } 435 436 437 438 void SAL_CALL 439 BaseContent::addPropertiesChangeListener( 440 const Sequence< rtl::OUString >& PropertyNames, 441 const Reference< beans::XPropertiesChangeListener >& Listener ) 442 { 443 if( ! Listener.is() ) 444 return; 445 446 osl::MutexGuard aGuard( m_aMutex ); 447 448 if( ! m_pPropertyListener ) 449 m_pPropertyListener = new PropertyListeners( m_aEventListenerMutex ); 450 451 452 if( PropertyNames.getLength() == 0 ) 453 m_pPropertyListener->addInterface( rtl::OUString(),Listener ); 454 else 455 { 456 Reference< beans::XPropertySetInfo > xProp = m_pMyShell->info_p( m_aUncPath ); 457 for( sal_Int32 i = 0; i < PropertyNames.getLength(); ++i ) 458 if( xProp->hasPropertyByName( PropertyNames[i] ) ) 459 m_pPropertyListener->addInterface( PropertyNames[i],Listener ); 460 } 461 } 462 463 464 void SAL_CALL 465 BaseContent::removePropertiesChangeListener( const Sequence< rtl::OUString >& PropertyNames, 466 const Reference< beans::XPropertiesChangeListener >& Listener ) 467 { 468 if( ! Listener.is() ) 469 return; 470 471 osl::MutexGuard aGuard( m_aMutex ); 472 473 if( ! m_pPropertyListener ) 474 return; 475 476 for( sal_Int32 i = 0; i < PropertyNames.getLength(); ++i ) 477 m_pPropertyListener->removeInterface( PropertyNames[i],Listener ); 478 479 m_pPropertyListener->removeInterface( rtl::OUString(), Listener ); 480 } 481 482 483 ///////////////////////////////////////////////////////////////////////////////////////// 484 // XContent 485 ///////////////////////////////////////////////////////////////////////////////////////// 486 487 Reference< ucb::XContentIdentifier > SAL_CALL 488 BaseContent::getIdentifier() 489 { 490 return m_xContentIdentifier; 491 } 492 493 494 rtl::OUString SAL_CALL 495 BaseContent::getContentType() 496 { 497 if( !( m_nState & Deleted ) ) 498 { 499 if( m_nState & JustInserted ) 500 { 501 if ( m_bFolder ) 502 return m_pMyShell->FolderContentType; 503 else 504 return m_pMyShell->FileContentType; 505 } 506 else 507 { 508 try 509 { 510 // Who am I ? 511 Sequence< beans::Property > seq(1); 512 seq[0] = beans::Property( rtl::OUString::createFromAscii("IsDocument"), 513 -1, 514 getCppuType( static_cast< sal_Bool* >(0) ), 515 0 ); 516 Reference< sdbc::XRow > xRow = getPropertyValues( -1,seq ); 517 sal_Bool IsDocument = xRow->getBoolean( 1 ); 518 519 if ( !xRow->wasNull() ) 520 { 521 if ( IsDocument ) 522 return m_pMyShell->FileContentType; 523 else 524 return m_pMyShell->FolderContentType; 525 } 526 else 527 { 528 OSL_ENSURE( false, 529 "BaseContent::getContentType - Property value was null!" ); 530 } 531 } 532 catch ( sdbc::SQLException const & ) 533 { 534 OSL_ENSURE( false, 535 "BaseContent::getContentType - Caught SQLException!" ); 536 } 537 } 538 } 539 540 return rtl::OUString(); 541 } 542 543 544 545 void SAL_CALL 546 BaseContent::addContentEventListener( 547 const Reference< XContentEventListener >& Listener ) 548 { 549 osl::MutexGuard aGuard( m_aMutex ); 550 551 if ( ! m_pContentEventListeners ) 552 m_pContentEventListeners = 553 new cppu::OInterfaceContainerHelper( m_aEventListenerMutex ); 554 555 556 m_pContentEventListeners->addInterface( Listener ); 557 } 558 559 560 void SAL_CALL 561 BaseContent::removeContentEventListener( 562 const Reference< XContentEventListener >& Listener ) 563 { 564 osl::MutexGuard aGuard( m_aMutex ); 565 566 if ( m_pContentEventListeners ) 567 m_pContentEventListeners->removeInterface( Listener ); 568 } 569 570 571 572 //////////////////////////////////////////////////////////////////////////////// 573 // XPropertyContainer 574 //////////////////////////////////////////////////////////////////////////////// 575 576 577 void SAL_CALL 578 BaseContent::addProperty( 579 const rtl::OUString& Name, 580 sal_Int16 Attributes, 581 const Any& DefaultValue ) 582 { 583 if( ( m_nState & JustInserted ) || ( m_nState & Deleted ) || Name == rtl::OUString() ) 584 { 585 throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 0 ); 586 } 587 588 m_pMyShell->associate( m_aUncPath,Name,DefaultValue,Attributes ); 589 } 590 591 592 void SAL_CALL 593 BaseContent::removeProperty( 594 const rtl::OUString& Name ) 595 { 596 597 if( m_nState & Deleted ) 598 throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 599 600 m_pMyShell->deassociate( m_aUncPath, Name ); 601 } 602 603 //////////////////////////////////////////////////////////////////////////////// 604 // XContentCreator 605 //////////////////////////////////////////////////////////////////////////////// 606 607 Sequence< ContentInfo > SAL_CALL 608 BaseContent::queryCreatableContentsInfo( 609 void ) 610 { 611 return m_pMyShell->queryCreatableContentsInfo(); 612 } 613 614 615 Reference< XContent > SAL_CALL 616 BaseContent::createNewContent( 617 const ContentInfo& Info ) 618 { 619 // Check type. 620 if ( !Info.Type.getLength() ) 621 return Reference< XContent >(); 622 623 sal_Bool bFolder 624 = ( Info.Type.compareTo( m_pMyShell->FolderContentType ) == 0 ); 625 if ( !bFolder ) 626 { 627 if ( Info.Type.compareTo( m_pMyShell->FileContentType ) != 0 ) 628 { 629 // Neither folder nor file to create! 630 return Reference< XContent >(); 631 } 632 } 633 634 // Who am I ? 635 sal_Bool IsDocument = false; 636 637 try 638 { 639 Sequence< beans::Property > seq(1); 640 seq[0] = beans::Property( rtl::OUString::createFromAscii("IsDocument"), 641 -1, 642 getCppuType( static_cast< sal_Bool* >(0) ), 643 0 ); 644 Reference< sdbc::XRow > xRow = getPropertyValues( -1,seq ); 645 IsDocument = xRow->getBoolean( 1 ); 646 647 if ( xRow->wasNull() ) 648 { 649 IsDocument = false; 650 // OSL_ENSURE( false, 651 // "BaseContent::createNewContent - Property value was null!" ); 652 // return Reference< XContent >(); 653 } 654 } 655 catch ( sdbc::SQLException const & ) 656 { 657 OSL_ENSURE( false, 658 "BaseContent::createNewContent - Caught SQLException!" ); 659 return Reference< XContent >(); 660 } 661 662 rtl::OUString dstUncPath; 663 664 if( IsDocument ) 665 { 666 // KSO: Why is a document a XContentCreator? This is quite unusual. 667 dstUncPath = getParentName( m_aUncPath ); 668 } 669 else 670 dstUncPath = m_aUncPath; 671 672 BaseContent* p = new BaseContent( m_pMyShell, dstUncPath, bFolder ); 673 return Reference< XContent >( p ); 674 } 675 676 677 //////////////////////////////////////////////////////////////////////////////// 678 // XPropertySetInfoChangeNotifier 679 //////////////////////////////////////////////////////////////////////////////// 680 681 682 void SAL_CALL 683 BaseContent::addPropertySetInfoChangeListener( 684 const Reference< beans::XPropertySetInfoChangeListener >& Listener ) 685 { 686 osl::MutexGuard aGuard( m_aMutex ); 687 if( ! m_pPropertySetInfoChangeListeners ) 688 m_pPropertySetInfoChangeListeners = new cppu::OInterfaceContainerHelper( m_aEventListenerMutex ); 689 690 m_pPropertySetInfoChangeListeners->addInterface( Listener ); 691 } 692 693 694 void SAL_CALL 695 BaseContent::removePropertySetInfoChangeListener( 696 const Reference< beans::XPropertySetInfoChangeListener >& Listener ) 697 { 698 osl::MutexGuard aGuard( m_aMutex ); 699 700 if( m_pPropertySetInfoChangeListeners ) 701 m_pPropertySetInfoChangeListeners->removeInterface( Listener ); 702 } 703 704 705 //////////////////////////////////////////////////////////////////////////////// 706 // XChild 707 //////////////////////////////////////////////////////////////////////////////// 708 709 Reference< XInterface > SAL_CALL 710 BaseContent::getParent( 711 void ) 712 { 713 rtl::OUString ParentUnq = getParentName( m_aUncPath ); 714 rtl::OUString ParentUrl; 715 716 717 sal_Bool err = m_pMyShell->getUrlFromUnq( ParentUnq, ParentUrl ); 718 if( err ) 719 return Reference< XInterface >( 0 ); 720 721 FileContentIdentifier* p = new FileContentIdentifier( m_pMyShell,ParentUnq ); 722 Reference< XContentIdentifier > Identifier( p ); 723 724 try 725 { 726 Reference< XContent > content = m_pMyShell->m_pProvider->queryContent( Identifier ); 727 return Reference<XInterface>(content,UNO_QUERY); 728 } 729 catch( IllegalIdentifierException ) 730 { 731 return Reference< XInterface >(); 732 } 733 } 734 735 736 void SAL_CALL 737 BaseContent::setParent( 738 const Reference< XInterface >& ) 739 { 740 throw lang::NoSupportException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 741 } 742 743 744 ////////////////////////////////////////////////////////////////////////////////////////// 745 // Private Methods 746 ////////////////////////////////////////////////////////////////////////////////////////// 747 748 749 Reference< XCommandInfo > SAL_CALL 750 BaseContent::getCommandInfo() 751 { 752 if( m_nState & Deleted ) 753 return Reference< XCommandInfo >(); 754 755 return m_pMyShell->info_c(); 756 } 757 758 759 Reference< beans::XPropertySetInfo > SAL_CALL 760 BaseContent::getPropertySetInfo( 761 sal_Int32 ) 762 { 763 if( m_nState & Deleted ) 764 return Reference< beans::XPropertySetInfo >(); 765 766 return m_pMyShell->info_p( m_aUncPath ); 767 } 768 769 770 771 772 Reference< sdbc::XRow > SAL_CALL 773 BaseContent::getPropertyValues( 774 sal_Int32 nMyCommandIdentifier, 775 const Sequence< beans::Property >& PropertySet ) 776 { 777 sal_Int32 nProps = PropertySet.getLength(); 778 if ( !nProps ) 779 return Reference< sdbc::XRow >(); 780 781 if( m_nState & Deleted ) 782 { 783 Sequence< Any > aValues( nProps ); 784 return Reference< sdbc::XRow >( new XRow_impl( m_pMyShell, aValues ) ); 785 } 786 787 if( m_nState & JustInserted ) 788 { 789 Sequence< Any > aValues( nProps ); 790 Any* pValues = aValues.getArray(); 791 792 const beans::Property* pProps = PropertySet.getConstArray(); 793 794 for ( sal_Int32 n = 0; n < nProps; ++n ) 795 { 796 const beans::Property& rProp = pProps[ n ]; 797 Any& rValue = pValues[ n ]; 798 799 if( rProp.Name.compareToAscii( "ContentType" ) == 0 ) 800 { 801 rValue <<= m_bFolder ? m_pMyShell->FolderContentType 802 : m_pMyShell->FileContentType; 803 } 804 else if( rProp.Name.compareToAscii( "IsFolder" ) == 0 ) 805 { 806 rValue <<= m_bFolder; 807 } 808 else if( rProp.Name.compareToAscii( "IsDocument" ) == 0 ) 809 { 810 rValue <<= sal_Bool( !m_bFolder ); 811 } 812 } 813 814 return Reference< sdbc::XRow >( 815 new XRow_impl( m_pMyShell, aValues ) ); 816 } 817 818 return m_pMyShell->getv( nMyCommandIdentifier, 819 m_aUncPath, 820 PropertySet ); 821 } 822 823 824 Sequence< Any > SAL_CALL 825 BaseContent::setPropertyValues( 826 sal_Int32 nMyCommandIdentifier, 827 const Sequence< beans::PropertyValue >& Values ) 828 throw() 829 { 830 if( m_nState & Deleted ) 831 { // To do 832 return Sequence< Any >( Values.getLength() ); 833 } 834 835 const rtl::OUString Title = rtl::OUString::createFromAscii( "Title" ); 836 837 // Special handling for files which have to be inserted 838 if( m_nState & JustInserted ) 839 { 840 for( sal_Int32 i = 0; i < Values.getLength(); ++i ) 841 { 842 if( Values[i].Name == Title ) 843 { 844 rtl::OUString NewTitle; 845 if( Values[i].Value >>= NewTitle ) 846 { 847 if ( m_nState & NameForInsertionSet ) 848 { 849 // User wants to set another Title before "insert". 850 // m_aUncPath contains previous own URI. 851 852 sal_Int32 nLastSlash = m_aUncPath.lastIndexOf( '/' ); 853 bool bTrailingSlash = false; 854 if ( nLastSlash == m_aUncPath.getLength() - 1 ) 855 { 856 bTrailingSlash = true; 857 nLastSlash 858 = m_aUncPath.lastIndexOf( '/', nLastSlash ); 859 } 860 861 OSL_ENSURE( nLastSlash != -1, 862 "BaseContent::setPropertyValues: " 863 "Invalid URL!" ); 864 865 rtl::OUStringBuffer aBuf( 866 m_aUncPath.copy( 0, nLastSlash + 1 ) ); 867 868 if ( NewTitle.getLength() > 0 ) 869 { 870 aBuf.append( NewTitle ); 871 if ( bTrailingSlash ) 872 aBuf.append( sal_Unicode( '/' ) ); 873 } 874 else 875 { 876 m_nState &= ~NameForInsertionSet; 877 } 878 879 m_aUncPath = aBuf.makeStringAndClear(); 880 } 881 else 882 { 883 if ( NewTitle.getLength() > 0 ) 884 { 885 // Initial Title before "insert". 886 // m_aUncPath contains parent's URI. 887 888 if( m_aUncPath.lastIndexOf( sal_Unicode('/') ) != m_aUncPath.getLength() - 1 ) 889 m_aUncPath += rtl::OUString::createFromAscii("/"); 890 891 m_aUncPath += rtl::Uri::encode( NewTitle, 892 rtl_UriCharClassPchar, 893 rtl_UriEncodeIgnoreEscapes, 894 RTL_TEXTENCODING_UTF8 ); 895 m_nState |= NameForInsertionSet; 896 } 897 } 898 } 899 } 900 } 901 902 return Sequence< Any >( Values.getLength() ); 903 } 904 else 905 { 906 Sequence< Any > ret = m_pMyShell->setv( m_aUncPath, // Does not handle Title 907 Values ); 908 909 // Special handling Title: Setting Title is equivalent to a renaming of the underlying file 910 for( sal_Int32 i = 0; i < Values.getLength(); ++i ) 911 { 912 if( Values[i].Name != Title ) 913 continue; // handled by setv 914 915 rtl::OUString NewTitle; 916 if( !( Values[i].Value >>= NewTitle ) ) 917 { 918 ret[i] <<= beans::IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 919 break; 920 } 921 else if( ! NewTitle.getLength() ) 922 { 923 ret[i] <<= lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 0 ); 924 break; 925 } 926 927 928 rtl::OUString aDstName = getParentName( m_aUncPath ); 929 if( aDstName.lastIndexOf( sal_Unicode('/') ) != aDstName.getLength() - 1 ) 930 aDstName += rtl::OUString::createFromAscii("/"); 931 932 aDstName += rtl::Uri::encode( NewTitle, 933 rtl_UriCharClassPchar, 934 rtl_UriEncodeIgnoreEscapes, 935 RTL_TEXTENCODING_UTF8 ); 936 937 m_pMyShell->move( nMyCommandIdentifier, // move notifies the childs also; 938 m_aUncPath, 939 aDstName, 940 NameClash::KEEP ); 941 942 try 943 { 944 endTask( nMyCommandIdentifier ); 945 } 946 catch( const Exception& e ) 947 { 948 ret[i] <<= e; 949 } 950 951 // NameChanges come back through a ContentEvent 952 break; // only handling Title 953 } // end for 954 955 return ret; 956 } 957 } 958 959 960 961 Reference< XDynamicResultSet > SAL_CALL 962 BaseContent::open( 963 sal_Int32 nMyCommandIdentifier, 964 const OpenCommandArgument2& aCommandArgument ) 965 throw() 966 { 967 Reference< XDynamicResultSet > retValue( 0 ); 968 969 if( ( m_nState & Deleted ) ) 970 { 971 m_pMyShell->installError( nMyCommandIdentifier, 972 TASKHANDLING_DELETED_STATE_IN_OPEN_COMMAND ); 973 } 974 else if( m_nState & JustInserted ) 975 { 976 m_pMyShell->installError( nMyCommandIdentifier, 977 TASKHANDLING_INSERTED_STATE_IN_OPEN_COMMAND ); 978 } 979 else 980 { 981 if( aCommandArgument.Mode == OpenMode::DOCUMENT || 982 aCommandArgument.Mode == OpenMode::DOCUMENT_SHARE_DENY_NONE ) 983 984 { 985 Reference< io::XOutputStream > outputStream( aCommandArgument.Sink,UNO_QUERY ); 986 if( outputStream.is() ) 987 { 988 m_pMyShell->page( nMyCommandIdentifier, 989 m_aUncPath, 990 outputStream ); 991 } 992 993 sal_Bool bLock = ( aCommandArgument.Mode != OpenMode::DOCUMENT_SHARE_DENY_NONE ); 994 995 Reference< io::XActiveDataSink > activeDataSink( aCommandArgument.Sink,UNO_QUERY ); 996 if( activeDataSink.is() ) 997 { 998 activeDataSink->setInputStream( m_pMyShell->open( nMyCommandIdentifier, 999 m_aUncPath, 1000 bLock ) ); 1001 } 1002 1003 Reference< io::XActiveDataStreamer > activeDataStreamer( aCommandArgument.Sink,UNO_QUERY ); 1004 if( activeDataStreamer.is() ) 1005 { 1006 activeDataStreamer->setStream( m_pMyShell->open_rw( nMyCommandIdentifier, 1007 m_aUncPath, 1008 bLock ) ); 1009 } 1010 } 1011 else if ( aCommandArgument.Mode == OpenMode::ALL || 1012 aCommandArgument.Mode == OpenMode::FOLDERS || 1013 aCommandArgument.Mode == OpenMode::DOCUMENTS ) 1014 { 1015 retValue = m_pMyShell->ls( nMyCommandIdentifier, 1016 m_aUncPath, 1017 aCommandArgument.Mode, 1018 aCommandArgument.Properties, 1019 aCommandArgument.SortingInfo ); 1020 } 1021 // else if( aCommandArgument.Mode == 1022 // OpenMode::DOCUMENT_SHARE_DENY_NONE || 1023 // aCommandArgument.Mode == 1024 // OpenMode::DOCUMENT_SHARE_DENY_WRITE ) 1025 // m_pMyShell->installError( nMyCommandIdentifier, 1026 // TASKHANDLING_UNSUPPORTED_OPEN_MODE, 1027 // aCommandArgument.Mode); 1028 else 1029 m_pMyShell->installError( nMyCommandIdentifier, 1030 TASKHANDLING_UNSUPPORTED_OPEN_MODE, 1031 aCommandArgument.Mode); 1032 } 1033 1034 return retValue; 1035 } 1036 1037 1038 1039 void SAL_CALL 1040 BaseContent::deleteContent( sal_Int32 nMyCommandIdentifier ) 1041 throw() 1042 { 1043 if( m_nState & Deleted ) 1044 return; 1045 1046 if( m_pMyShell->remove( nMyCommandIdentifier,m_aUncPath ) ) 1047 { 1048 osl::MutexGuard aGuard( m_aMutex ); 1049 m_nState |= Deleted; 1050 } 1051 } 1052 1053 1054 1055 void SAL_CALL 1056 BaseContent::transfer( sal_Int32 nMyCommandIdentifier, 1057 const TransferInfo& aTransferInfo ) 1058 throw() 1059 { 1060 if( m_nState & Deleted ) 1061 return; 1062 1063 if( aTransferInfo.SourceURL.compareToAscii( "file:",5 ) != 0 ) 1064 { 1065 m_pMyShell->installError( nMyCommandIdentifier, 1066 TASKHANDLING_TRANSFER_INVALIDSCHEME ); 1067 return; 1068 } 1069 1070 rtl::OUString srcUnc; 1071 if( m_pMyShell->getUnqFromUrl( aTransferInfo.SourceURL,srcUnc ) ) 1072 { 1073 m_pMyShell->installError( nMyCommandIdentifier, 1074 TASKHANDLING_TRANSFER_INVALIDURL ); 1075 return; 1076 } 1077 1078 rtl::OUString srcUncPath = srcUnc; 1079 1080 // Determine the new title ! 1081 rtl::OUString NewTitle; 1082 if( aTransferInfo.NewTitle.getLength() ) 1083 NewTitle = rtl::Uri::encode( aTransferInfo.NewTitle, 1084 rtl_UriCharClassPchar, 1085 rtl_UriEncodeIgnoreEscapes, 1086 RTL_TEXTENCODING_UTF8 ); 1087 else 1088 NewTitle = srcUncPath.copy( 1 + srcUncPath.lastIndexOf( sal_Unicode('/') ) ); 1089 1090 // Is destination a document or a folder ? 1091 Sequence< beans::Property > seq(1); 1092 seq[0] = beans::Property( rtl::OUString::createFromAscii("IsDocument"), 1093 -1, 1094 getCppuType( static_cast< sal_Bool* >(0) ), 1095 0 ); 1096 Reference< sdbc::XRow > xRow = getPropertyValues( nMyCommandIdentifier,seq ); 1097 sal_Bool IsDocument = xRow->getBoolean( 1 ); 1098 if( xRow->wasNull() ) 1099 { // Destination file type could not be determined 1100 m_pMyShell->installError( nMyCommandIdentifier, 1101 TASKHANDLING_TRANSFER_DESTFILETYPE ); 1102 return; 1103 } 1104 1105 rtl::OUString dstUncPath; 1106 if( IsDocument ) 1107 { // as sibling 1108 sal_Int32 lastSlash = m_aUncPath.lastIndexOf( sal_Unicode('/') ); 1109 dstUncPath = m_aUncPath.copy(0,lastSlash ); 1110 } 1111 else 1112 // as child 1113 dstUncPath = m_aUncPath; 1114 1115 dstUncPath += ( rtl::OUString::createFromAscii( "/" ) + NewTitle ); 1116 1117 sal_Int32 NameClash = aTransferInfo.NameClash; 1118 1119 if( aTransferInfo.MoveData ) 1120 m_pMyShell->move( nMyCommandIdentifier,srcUncPath,dstUncPath,NameClash ); 1121 else 1122 m_pMyShell->copy( nMyCommandIdentifier,srcUncPath,dstUncPath,NameClash ); 1123 } 1124 1125 1126 1127 1128 void SAL_CALL BaseContent::insert( sal_Int32 nMyCommandIdentifier, 1129 const InsertCommandArgument& aInsertArgument ) 1130 throw() 1131 { 1132 if( m_nState & FullFeatured ) 1133 { 1134 m_pMyShell->write( nMyCommandIdentifier, 1135 m_aUncPath, 1136 aInsertArgument.ReplaceExisting, 1137 aInsertArgument.Data ); 1138 return; 1139 } 1140 1141 if( ! ( m_nState & JustInserted ) ) 1142 { 1143 m_pMyShell->installError( nMyCommandIdentifier, 1144 TASKHANDLING_NOFRESHINSERT_IN_INSERT_COMMAND ); 1145 return; 1146 } 1147 1148 // Inserts the content, which has the flag m_bIsFresh 1149 1150 if ( !m_nState | !NameForInsertionSet ) 1151 { 1152 m_pMyShell->installError( nMyCommandIdentifier, 1153 TASKHANDLING_NONAMESET_INSERT_COMMAND ); 1154 return; 1155 } 1156 1157 // Inserting a document or a file? 1158 sal_Bool bDocument = false; 1159 1160 Sequence< beans::Property > seq(1); 1161 seq[0] = beans::Property( rtl::OUString::createFromAscii("IsDocument"), 1162 -1, 1163 getCppuType( static_cast< sal_Bool* >(0) ), 1164 0 ); 1165 1166 Reference< sdbc::XRow > xRow = getPropertyValues( -1,seq ); 1167 1168 bool contentTypeSet = true; // is set to false, if contentType not set 1169 try 1170 { 1171 bDocument = xRow->getBoolean( 1 ); 1172 if( xRow->wasNull() ) 1173 contentTypeSet = false; 1174 1175 } 1176 catch ( sdbc::SQLException const & ) 1177 { 1178 OSL_ENSURE( false, 1179 "BaseContent::insert - Caught SQLException!" ); 1180 contentTypeSet = false; 1181 } 1182 1183 if( ! contentTypeSet ) 1184 { 1185 m_pMyShell->installError( nMyCommandIdentifier, 1186 TASKHANDLING_NOCONTENTTYPE_INSERT_COMMAND ); 1187 return; 1188 } 1189 1190 1191 sal_Bool success = false; 1192 if( bDocument ) 1193 success = m_pMyShell->mkfil( nMyCommandIdentifier, 1194 m_aUncPath, 1195 aInsertArgument.ReplaceExisting, 1196 aInsertArgument.Data ); 1197 else 1198 { 1199 while( ! success ) 1200 { 1201 success = m_pMyShell->mkdir( nMyCommandIdentifier, 1202 m_aUncPath, 1203 aInsertArgument.ReplaceExisting ); 1204 if( success ) 1205 break; 1206 1207 XInteractionRequestImpl *aRequestImpl = 1208 new XInteractionRequestImpl( 1209 rtl::Uri::decode( 1210 getTitle(m_aUncPath), 1211 rtl_UriDecodeWithCharset, 1212 RTL_TEXTENCODING_UTF8), 1213 (cppu::OWeakObject*)this, 1214 m_pMyShell,nMyCommandIdentifier); 1215 uno::Reference< task::XInteractionRequest > aReq( aRequestImpl ); 1216 1217 m_pMyShell->handleTask( nMyCommandIdentifier,aReq ); 1218 if( aRequestImpl->aborted() || 1219 !aRequestImpl->newName().getLength() ) 1220 // means aborting 1221 break; 1222 1223 // determine new uncpath 1224 m_pMyShell->clearError( nMyCommandIdentifier ); 1225 m_aUncPath = getParentName( m_aUncPath ); 1226 if( m_aUncPath.lastIndexOf( sal_Unicode('/') ) != m_aUncPath.getLength() - 1 ) 1227 m_aUncPath += rtl::OUString::createFromAscii("/"); 1228 1229 m_aUncPath += rtl::Uri::encode( aRequestImpl->newName(), 1230 rtl_UriCharClassPchar, 1231 rtl_UriEncodeIgnoreEscapes, 1232 RTL_TEXTENCODING_UTF8 ); 1233 } 1234 } 1235 1236 if ( ! success ) 1237 return; 1238 1239 FileContentIdentifier* p = new FileContentIdentifier( m_pMyShell,m_aUncPath ); 1240 m_xContentIdentifier = Reference< XContentIdentifier >( p ); 1241 1242 m_pMyShell->registerNotifier( m_aUncPath,this ); 1243 m_pMyShell->insertDefaultProperties( m_aUncPath ); 1244 1245 osl::MutexGuard aGuard( m_aMutex ); 1246 m_nState = FullFeatured; 1247 } 1248 1249 1250 1251 void SAL_CALL BaseContent::endTask( sal_Int32 CommandId ) 1252 { 1253 // This is the only function allowed to throw an exception 1254 m_pMyShell->endTask( CommandId,m_aUncPath,this ); 1255 } 1256 1257 1258 1259 ContentEventNotifier* 1260 BaseContent::cDEL( void ) 1261 { 1262 osl::MutexGuard aGuard( m_aMutex ); 1263 1264 m_nState |= Deleted; 1265 1266 ContentEventNotifier* p; 1267 if( m_pContentEventListeners ) 1268 p = new ContentEventNotifier( m_pMyShell, 1269 this, 1270 m_xContentIdentifier, 1271 m_pContentEventListeners->getElements() ); 1272 else 1273 p = 0; 1274 1275 return p; 1276 } 1277 1278 1279 ContentEventNotifier* 1280 BaseContent::cEXC( const rtl::OUString aNewName ) 1281 { 1282 osl::MutexGuard aGuard( m_aMutex ); 1283 1284 Reference< XContentIdentifier > xOldRef = m_xContentIdentifier; 1285 m_aUncPath = aNewName; 1286 FileContentIdentifier* pp = new FileContentIdentifier( m_pMyShell,aNewName ); 1287 m_xContentIdentifier = Reference< XContentIdentifier >( pp ); 1288 1289 ContentEventNotifier* p = 0; 1290 if( m_pContentEventListeners ) 1291 p = new ContentEventNotifier( m_pMyShell, 1292 this, 1293 m_xContentIdentifier, 1294 xOldRef, 1295 m_pContentEventListeners->getElements() ); 1296 1297 return p; 1298 } 1299 1300 1301 ContentEventNotifier* 1302 BaseContent::cCEL( void ) 1303 { 1304 osl::MutexGuard aGuard( m_aMutex ); 1305 ContentEventNotifier* p = 0; 1306 if( m_pContentEventListeners ) 1307 p = new ContentEventNotifier( m_pMyShell, 1308 this, 1309 m_xContentIdentifier, 1310 m_pContentEventListeners->getElements() ); 1311 1312 return p; 1313 } 1314 1315 PropertySetInfoChangeNotifier* 1316 BaseContent::cPSL( void ) 1317 { 1318 osl::MutexGuard aGuard( m_aMutex ); 1319 PropertySetInfoChangeNotifier* p = 0; 1320 if( m_pPropertySetInfoChangeListeners ) 1321 p = new PropertySetInfoChangeNotifier( m_pMyShell, 1322 this, 1323 m_xContentIdentifier, 1324 m_pPropertySetInfoChangeListeners->getElements() ); 1325 1326 return p; 1327 } 1328 1329 1330 1331 PropertyChangeNotifier* 1332 BaseContent::cPCL( void ) 1333 { 1334 osl::MutexGuard aGuard( m_aMutex ); 1335 1336 Sequence< rtl::OUString > seqNames; 1337 1338 if( m_pPropertyListener ) 1339 seqNames = m_pPropertyListener->getContainedTypes(); 1340 1341 PropertyChangeNotifier* p = 0; 1342 1343 sal_Int32 length = seqNames.getLength(); 1344 1345 if( length ) 1346 { 1347 ListenerMap* listener = new ListenerMap(); 1348 for( sal_Int32 i = 0; i < length; ++i ) 1349 { 1350 (*listener)[seqNames[i]] = m_pPropertyListener->getContainer( seqNames[i] )->getElements(); 1351 } 1352 1353 p = new PropertyChangeNotifier( m_pMyShell, 1354 this, 1355 m_xContentIdentifier, 1356 listener ); 1357 } 1358 1359 return p; 1360 } 1361 1362 1363 rtl::OUString BaseContent::getKey( void ) 1364 { 1365 return m_aUncPath; 1366 } 1367 1368 /* vim: set noet sw=4 ts=4: */ 1369