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_ucb.hxx" 30 #ifndef INCLUDED_STL_STACK 31 #include <stack> 32 #define INCLUDED_STL_STACK 33 #endif 34 35 #include "osl/diagnose.h" 36 #include <rtl/uri.hxx> 37 #include <rtl/ustrbuf.hxx> 38 #include <osl/time.h> 39 #include <osl/file.hxx> 40 #include <com/sun/star/lang/IllegalAccessException.hpp> 41 #include <com/sun/star/beans/IllegalTypeException.hpp> 42 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> 43 #include <com/sun/star/ucb/InsertCommandArgument.hpp> 44 #include <com/sun/star/ucb/NameClash.hpp> 45 #include <com/sun/star/ucb/XContentIdentifier.hpp> 46 #include <com/sun/star/lang/XComponent.hpp> 47 #include <com/sun/star/ucb/XContentAccess.hpp> 48 #include <com/sun/star/beans/PropertyAttribute.hpp> 49 #include <com/sun/star/io/XSeekable.hpp> 50 #include <com/sun/star/io/XTruncate.hpp> 51 #include <com/sun/star/ucb/OpenCommandArgument.hpp> 52 #include <com/sun/star/ucb/XPropertySetRegistryFactory.hpp> 53 #include <com/sun/star/ucb/TransferInfo.hpp> 54 #include <com/sun/star/ucb/ContentInfoAttribute.hpp> 55 #include <com/sun/star/beans/PropertyChangeEvent.hpp> 56 #include <com/sun/star/beans/XPropertiesChangeListener.hpp> 57 #include <rtl/string.hxx> 58 #include "filerror.hxx" 59 #include "filglob.hxx" 60 #include "filcmd.hxx" 61 #include "filinpstr.hxx" 62 #include "filstr.hxx" 63 #include "filrset.hxx" 64 #include "filrow.hxx" 65 #include "filprp.hxx" 66 #include "filid.hxx" 67 #include "shell.hxx" 68 #include "prov.hxx" 69 #include "bc.hxx" 70 71 72 using namespace fileaccess; 73 using namespace com::sun::star; 74 using namespace com::sun::star::ucb; 75 76 77 shell::UnqPathData::UnqPathData() 78 : properties( 0 ), 79 notifier( 0 ), 80 xS( 0 ), 81 xC( 0 ), 82 xA( 0 ) 83 { 84 // empty 85 } 86 87 88 shell::UnqPathData::UnqPathData( const UnqPathData& a ) 89 : properties( a.properties ), 90 notifier( a.notifier ), 91 xS( a.xS ), 92 xC( a.xC ), 93 xA( a.xA ) 94 { 95 } 96 97 98 shell::UnqPathData& shell::UnqPathData::operator=( UnqPathData& a ) 99 { 100 properties = a.properties; 101 notifier = a.notifier; 102 xS = a.xS; 103 xC = a.xC; 104 xA = a.xA; 105 a.properties = 0; 106 a.notifier = 0; 107 a.xS = 0; 108 a.xC = 0; 109 a.xA = 0; 110 return *this; 111 } 112 113 shell::UnqPathData::~UnqPathData() 114 { 115 if( properties ) 116 delete properties; 117 if( notifier ) 118 delete notifier; 119 } 120 121 122 123 //////////////////////////////////////////////////////////////////////////////////////// 124 125 126 127 128 129 shell::MyProperty::MyProperty( const rtl::OUString& __PropertyName ) 130 : PropertyName( __PropertyName ) 131 { 132 // empty 133 } 134 135 136 shell::MyProperty::MyProperty( const sal_Bool& __isNative, 137 const rtl::OUString& __PropertyName, 138 const sal_Int32& __Handle, 139 const com::sun::star::uno::Type& __Typ, 140 const com::sun::star::uno::Any& __Value, 141 const com::sun::star::beans::PropertyState& __State, 142 const sal_Int16& __Attributes ) 143 : PropertyName( __PropertyName ), 144 Handle( __Handle ), 145 isNative( __isNative ), 146 Typ( __Typ ), 147 Value( __Value ), 148 State( __State ), 149 Attributes( __Attributes ) 150 { 151 // empty 152 } 153 154 shell::MyProperty::~MyProperty() 155 { 156 // empty for now 157 } 158 159 160 #include "filinl.hxx" 161 162 163 shell::shell( const uno::Reference< lang::XMultiServiceFactory >& xMultiServiceFactory, 164 FileProvider* pProvider, sal_Bool bWithConfig ) 165 : TaskManager(), 166 m_bWithConfig( bWithConfig ), 167 m_pProvider( pProvider ), 168 m_xMultiServiceFactory( xMultiServiceFactory ), 169 Title( rtl::OUString::createFromAscii( "Title" ) ), 170 CasePreservingURL( 171 rtl::OUString::createFromAscii( "CasePreservingURL" ) ), 172 IsDocument( rtl::OUString::createFromAscii( "IsDocument" ) ), 173 IsFolder( rtl::OUString::createFromAscii( "IsFolder" ) ), 174 DateModified( rtl::OUString::createFromAscii( "DateModified" ) ), 175 Size( rtl::OUString::createFromAscii( "Size" ) ), 176 IsVolume( rtl::OUString::createFromAscii( "IsVolume" ) ), 177 IsRemoveable( rtl::OUString::createFromAscii( "IsRemoveable" ) ), 178 IsRemote( rtl::OUString::createFromAscii( "IsRemote" ) ), 179 IsCompactDisc( rtl::OUString::createFromAscii( "IsCompactDisc" ) ), 180 IsFloppy( rtl::OUString::createFromAscii( "IsFloppy" ) ), 181 IsHidden( rtl::OUString::createFromAscii( "IsHidden" ) ), 182 ContentType( rtl::OUString::createFromAscii( "ContentType" ) ), 183 IsReadOnly( rtl::OUString::createFromAscii( "IsReadOnly" ) ), 184 CreatableContentsInfo( rtl::OUString::createFromAscii( "CreatableContentsInfo" ) ), 185 FolderContentType( rtl::OUString::createFromAscii( "application/vnd.sun.staroffice.fsys-folder" ) ), 186 FileContentType( rtl::OUString::createFromAscii( "application/vnd.sun.staroffice.fsys-file" ) ), 187 m_sCommandInfo( 9 ) 188 { 189 // Title 190 m_aDefaultProperties.insert( MyProperty( true, 191 Title, 192 -1 , 193 getCppuType( static_cast< rtl::OUString* >( 0 ) ), 194 uno::Any(), 195 beans::PropertyState_DEFAULT_VALUE, 196 beans::PropertyAttribute::MAYBEVOID 197 | beans::PropertyAttribute::BOUND ) ); 198 199 // CasePreservingURL 200 m_aDefaultProperties.insert( 201 MyProperty( true, 202 CasePreservingURL, 203 -1 , 204 getCppuType( static_cast< rtl::OUString* >( 0 ) ), 205 uno::Any(), 206 beans::PropertyState_DEFAULT_VALUE, 207 beans::PropertyAttribute::MAYBEVOID 208 | beans::PropertyAttribute::BOUND 209 | beans::PropertyAttribute::READONLY ) ); 210 211 212 // IsFolder 213 m_aDefaultProperties.insert( MyProperty( true, 214 IsFolder, 215 -1 , 216 getCppuType( static_cast< sal_Bool* >( 0 ) ), 217 uno::Any(), 218 beans::PropertyState_DEFAULT_VALUE, 219 beans::PropertyAttribute::MAYBEVOID 220 | beans::PropertyAttribute::BOUND 221 | beans::PropertyAttribute::READONLY ) ); 222 223 224 // IsDocument 225 m_aDefaultProperties.insert( MyProperty( true, 226 IsDocument, 227 -1 , 228 getCppuType( static_cast< sal_Bool* >( 0 ) ), 229 uno::Any(), 230 beans::PropertyState_DEFAULT_VALUE, 231 beans::PropertyAttribute::MAYBEVOID 232 | beans::PropertyAttribute::BOUND 233 | beans::PropertyAttribute::READONLY ) ); 234 235 // Removable 236 m_aDefaultProperties.insert( MyProperty( true, 237 IsVolume, 238 -1 , 239 getCppuType( static_cast< sal_Bool* >( 0 ) ), 240 uno::Any(), 241 beans::PropertyState_DEFAULT_VALUE, 242 beans::PropertyAttribute::MAYBEVOID 243 | beans::PropertyAttribute::BOUND 244 | beans::PropertyAttribute::READONLY ) ); 245 246 247 // Removable 248 m_aDefaultProperties.insert( MyProperty( true, 249 IsRemoveable, 250 -1 , 251 getCppuType( static_cast< sal_Bool* >( 0 ) ), 252 uno::Any(), 253 beans::PropertyState_DEFAULT_VALUE, 254 beans::PropertyAttribute::MAYBEVOID 255 | beans::PropertyAttribute::BOUND 256 | beans::PropertyAttribute::READONLY ) ); 257 258 // Remote 259 m_aDefaultProperties.insert( MyProperty( true, 260 IsRemote, 261 -1 , 262 getCppuType( static_cast< sal_Bool* >( 0 ) ), 263 uno::Any(), 264 beans::PropertyState_DEFAULT_VALUE, 265 beans::PropertyAttribute::MAYBEVOID 266 | beans::PropertyAttribute::BOUND 267 | beans::PropertyAttribute::READONLY ) ); 268 269 // CompactDisc 270 m_aDefaultProperties.insert( MyProperty( true, 271 IsCompactDisc, 272 -1 , 273 getCppuType( static_cast< sal_Bool* >( 0 ) ), 274 uno::Any(), 275 beans::PropertyState_DEFAULT_VALUE, 276 beans::PropertyAttribute::MAYBEVOID 277 | beans::PropertyAttribute::BOUND 278 | beans::PropertyAttribute::READONLY ) ); 279 280 // Floppy 281 m_aDefaultProperties.insert( MyProperty( true, 282 IsFloppy, 283 -1 , 284 getCppuType( static_cast< sal_Bool* >( 0 ) ), 285 uno::Any(), 286 beans::PropertyState_DEFAULT_VALUE, 287 beans::PropertyAttribute::MAYBEVOID 288 | beans::PropertyAttribute::BOUND 289 | beans::PropertyAttribute::READONLY ) ); 290 291 // Hidden 292 m_aDefaultProperties.insert( 293 MyProperty( 294 true, 295 IsHidden, 296 -1 , 297 getCppuType( static_cast< sal_Bool* >( 0 ) ), 298 uno::Any(), 299 beans::PropertyState_DEFAULT_VALUE, 300 beans::PropertyAttribute::MAYBEVOID 301 | beans::PropertyAttribute::BOUND 302 #if defined( WNT ) || defined( OS2 ) 303 )); 304 #else 305 | beans::PropertyAttribute::READONLY)); // under unix/linux only readable 306 #endif 307 308 309 // ContentType 310 uno::Any aAny; 311 aAny <<= rtl::OUString(); 312 m_aDefaultProperties.insert( MyProperty( false, 313 ContentType, 314 -1 , 315 getCppuType( static_cast< rtl::OUString* >( 0 ) ), 316 aAny, 317 beans::PropertyState_DEFAULT_VALUE, 318 beans::PropertyAttribute::MAYBEVOID 319 | beans::PropertyAttribute::BOUND 320 | beans::PropertyAttribute::READONLY ) ); 321 322 323 // DateModified 324 m_aDefaultProperties.insert( MyProperty( true, 325 DateModified, 326 -1 , 327 getCppuType( static_cast< util::DateTime* >( 0 ) ), 328 uno::Any(), 329 beans::PropertyState_DEFAULT_VALUE, 330 beans::PropertyAttribute::MAYBEVOID 331 | beans::PropertyAttribute::BOUND ) ); 332 333 // Size 334 m_aDefaultProperties.insert( MyProperty( true, 335 Size, 336 -1, 337 getCppuType( static_cast< sal_Int64* >( 0 ) ), 338 uno::Any(), 339 beans::PropertyState_DEFAULT_VALUE, 340 beans::PropertyAttribute::MAYBEVOID 341 | beans::PropertyAttribute::BOUND ) ); 342 343 // IsReadOnly 344 m_aDefaultProperties.insert( MyProperty( true, 345 IsReadOnly, 346 -1 , 347 getCppuType( static_cast< sal_Bool* >( 0 ) ), 348 uno::Any(), 349 beans::PropertyState_DEFAULT_VALUE, 350 beans::PropertyAttribute::MAYBEVOID 351 | beans::PropertyAttribute::BOUND ) ); 352 353 354 // CreatableContentsInfo 355 m_aDefaultProperties.insert( MyProperty( true, 356 CreatableContentsInfo, 357 -1 , 358 getCppuType( static_cast< const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), 359 uno::Any(), 360 beans::PropertyState_DEFAULT_VALUE, 361 beans::PropertyAttribute::MAYBEVOID 362 | beans::PropertyAttribute::BOUND 363 | beans::PropertyAttribute::READONLY ) ); 364 365 // Commands 366 m_sCommandInfo[0].Name = rtl::OUString::createFromAscii( "getCommandInfo" ); 367 m_sCommandInfo[0].Handle = -1; 368 m_sCommandInfo[0].ArgType = getCppuVoidType(); 369 370 m_sCommandInfo[1].Name = rtl::OUString::createFromAscii( "getPropertySetInfo" ); 371 m_sCommandInfo[1].Handle = -1; 372 m_sCommandInfo[1].ArgType = getCppuVoidType(); 373 374 m_sCommandInfo[2].Name = rtl::OUString::createFromAscii( "getPropertyValues" ); 375 m_sCommandInfo[2].Handle = -1; 376 m_sCommandInfo[2].ArgType = getCppuType( static_cast< uno::Sequence< beans::Property >* >( 0 ) ); 377 378 m_sCommandInfo[3].Name = rtl::OUString::createFromAscii( "setPropertyValues" ); 379 m_sCommandInfo[3].Handle = -1; 380 m_sCommandInfo[3].ArgType = getCppuType( static_cast< uno::Sequence< beans::PropertyValue >* >( 0 ) ); 381 382 m_sCommandInfo[4].Name = rtl::OUString::createFromAscii( "open" ); 383 m_sCommandInfo[4].Handle = -1; 384 m_sCommandInfo[4].ArgType = getCppuType( static_cast< OpenCommandArgument* >( 0 ) ); 385 386 m_sCommandInfo[5].Name = rtl::OUString::createFromAscii( "transfer" ); 387 m_sCommandInfo[5].Handle = -1; 388 m_sCommandInfo[5].ArgType = getCppuType( static_cast< TransferInfo* >( 0 ) ); 389 390 m_sCommandInfo[6].Name = rtl::OUString::createFromAscii( "delete" ); 391 m_sCommandInfo[6].Handle = -1; 392 m_sCommandInfo[6].ArgType = getCppuType( static_cast< sal_Bool* >( 0 ) ); 393 394 m_sCommandInfo[7].Name = rtl::OUString::createFromAscii( "insert" ); 395 m_sCommandInfo[7].Handle = -1; 396 m_sCommandInfo[7].ArgType = getCppuType( static_cast< InsertCommandArgument* > ( 0 ) ); 397 398 m_sCommandInfo[7].Name = rtl::OUString::createFromAscii( "createNewContent" ); 399 m_sCommandInfo[7].Handle = -1; 400 m_sCommandInfo[7].ArgType = getCppuType( static_cast< ucb::ContentInfo * > ( 0 ) ); 401 402 if(m_bWithConfig) 403 { 404 rtl::OUString Store = rtl::OUString::createFromAscii( "com.sun.star.ucb.Store" ); 405 uno::Reference< XPropertySetRegistryFactory > xRegFac( 406 m_xMultiServiceFactory->createInstance( Store ), 407 uno::UNO_QUERY ); 408 if ( xRegFac.is() ) 409 { 410 // Open/create a registry 411 m_xFileRegistry = xRegFac->createPropertySetRegistry( rtl::OUString() ); 412 } 413 } 414 } 415 416 417 shell::~shell() 418 { 419 } 420 421 422 /*********************************************************************************/ 423 /* */ 424 /* de/registerNotifier-Implementation */ 425 /* */ 426 /*********************************************************************************/ 427 428 // 429 // This two methods register and deregister a change listener for the content belonging 430 // to URL aUnqPath 431 // 432 433 void SAL_CALL 434 shell::registerNotifier( const rtl::OUString& aUnqPath, Notifier* pNotifier ) 435 { 436 osl::MutexGuard aGuard( m_aMutex ); 437 438 ContentMap::iterator it = 439 m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first; 440 441 if( ! it->second.notifier ) 442 it->second.notifier = new NotifierList(); 443 444 std::list< Notifier* >& nlist = *( it->second.notifier ); 445 446 std::list<Notifier*>::iterator it1 = nlist.begin(); 447 while( it1 != nlist.end() ) // Every "Notifier" only once 448 { 449 if( *it1 == pNotifier ) return; 450 ++it1; 451 } 452 nlist.push_back( pNotifier ); 453 } 454 455 456 457 void SAL_CALL 458 shell::deregisterNotifier( const rtl::OUString& aUnqPath,Notifier* pNotifier ) 459 { 460 osl::MutexGuard aGuard( m_aMutex ); 461 462 ContentMap::iterator it = m_aContent.find( aUnqPath ); 463 if( it == m_aContent.end() ) 464 return; 465 466 it->second.notifier->remove( pNotifier ); 467 468 if( ! it->second.notifier->size() ) 469 m_aContent.erase( it ); 470 } 471 472 473 474 /*********************************************************************************/ 475 /* */ 476 /* de/associate-Implementation */ 477 /* */ 478 /*********************************************************************************/ 479 // 480 // Used to associate and deassociate a new property with 481 // the content belonging to URL UnqPath. 482 // The default value and the the attributes are input 483 // 484 485 void SAL_CALL 486 shell::associate( const rtl::OUString& aUnqPath, 487 const rtl::OUString& PropertyName, 488 const uno::Any& DefaultValue, 489 const sal_Int16 Attributes ) 490 throw( beans::PropertyExistException, 491 beans::IllegalTypeException, 492 uno::RuntimeException ) 493 { 494 MyProperty newProperty( false, 495 PropertyName, 496 -1, 497 DefaultValue.getValueType(), 498 DefaultValue, 499 beans::PropertyState_DEFAULT_VALUE, 500 Attributes ); 501 502 shell::PropertySet::iterator it1 = m_aDefaultProperties.find( newProperty ); 503 if( it1 != m_aDefaultProperties.end() ) 504 throw beans::PropertyExistException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 505 506 { 507 osl::MutexGuard aGuard( m_aMutex ); 508 509 ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first; 510 511 // Load the XPersistentPropertySetInfo and create it, if it does not exist 512 load( it,true ); 513 514 PropertySet& properties = *(it->second.properties); 515 it1 = properties.find( newProperty ); 516 if( it1 != properties.end() ) 517 throw beans::PropertyExistException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 518 519 // Property does not exist 520 properties.insert( newProperty ); 521 it->second.xC->addProperty( PropertyName,Attributes,DefaultValue ); 522 } 523 notifyPropertyAdded( getPropertySetListeners( aUnqPath ), PropertyName ); 524 } 525 526 527 528 529 void SAL_CALL 530 shell::deassociate( const rtl::OUString& aUnqPath, 531 const rtl::OUString& PropertyName ) 532 throw( beans::UnknownPropertyException, 533 beans::NotRemoveableException, 534 uno::RuntimeException ) 535 { 536 MyProperty oldProperty( PropertyName ); 537 538 shell::PropertySet::iterator it1 = m_aDefaultProperties.find( oldProperty ); 539 if( it1 != m_aDefaultProperties.end() ) 540 throw beans::NotRemoveableException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 541 542 osl::MutexGuard aGuard( m_aMutex ); 543 544 ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first; 545 546 load( it,false ); 547 548 PropertySet& properties = *(it->second.properties); 549 550 it1 = properties.find( oldProperty ); 551 if( it1 == properties.end() ) 552 throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 553 554 properties.erase( it1 ); 555 556 if( it->second.xC.is() ) 557 it->second.xC->removeProperty( PropertyName ); 558 559 if( properties.size() == 9 ) 560 { 561 MyProperty ContentTProperty( ContentType ); 562 563 if( properties.find( ContentTProperty )->getState() == beans::PropertyState_DEFAULT_VALUE ) 564 { 565 it->second.xS = 0; 566 it->second.xC = 0; 567 it->second.xA = 0; 568 if(m_xFileRegistry.is()) 569 m_xFileRegistry->removePropertySet( aUnqPath ); 570 } 571 } 572 notifyPropertyRemoved( getPropertySetListeners( aUnqPath ), PropertyName ); 573 } 574 575 576 577 578 /*********************************************************************************/ 579 /* */ 580 /* page-Implementation */ 581 /* */ 582 /*********************************************************************************/ 583 // 584 // Given an xOutputStream, this method writes the content of the file belonging to 585 // URL aUnqPath into the XOutputStream 586 // 587 588 589 void SAL_CALL shell::page( sal_Int32 CommandId, 590 const rtl::OUString& aUnqPath, 591 const uno::Reference< io::XOutputStream >& xOutputStream ) 592 throw() 593 { 594 uno::Reference< XContentProvider > xProvider( m_pProvider ); 595 osl::File aFile( aUnqPath ); 596 osl::FileBase::RC err = aFile.open( OpenFlag_Read ); 597 598 if( err != osl::FileBase::E_None ) 599 { 600 aFile.close(); 601 installError( CommandId, 602 TASKHANDLING_OPEN_FILE_FOR_PAGING, 603 err ); 604 return; 605 } 606 607 const sal_uInt64 bfz = 4*1024; 608 sal_Int8 BFF[bfz]; 609 sal_uInt64 nrc; // Retrieved number of Bytes; 610 611 do 612 { 613 err = aFile.read( (void*) BFF,bfz,nrc ); 614 if( err == osl::FileBase::E_None ) 615 { 616 uno::Sequence< sal_Int8 > seq( BFF, (sal_uInt32)nrc ); 617 try 618 { 619 xOutputStream->writeBytes( seq ); 620 } 621 catch( io::NotConnectedException ) 622 { 623 installError( CommandId, 624 TASKHANDLING_NOTCONNECTED_FOR_PAGING ); 625 break; 626 } 627 catch( io::BufferSizeExceededException ) 628 { 629 installError( CommandId, 630 TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_PAGING ); 631 break; 632 } 633 catch( io::IOException ) 634 { 635 installError( CommandId, 636 TASKHANDLING_IOEXCEPTION_FOR_PAGING ); 637 break; 638 } 639 } 640 else 641 { 642 installError( CommandId, 643 TASKHANDLING_READING_FILE_FOR_PAGING, 644 err ); 645 break; 646 } 647 } while( nrc == bfz ); 648 649 650 aFile.close(); 651 652 653 try 654 { 655 xOutputStream->closeOutput(); 656 } 657 catch( io::NotConnectedException ) 658 { 659 } 660 catch( io::BufferSizeExceededException ) 661 { 662 } 663 catch( io::IOException ) 664 { 665 } 666 } 667 668 669 /*********************************************************************************/ 670 /* */ 671 /* open-Implementation */ 672 /* */ 673 /*********************************************************************************/ 674 // 675 // Given a file URL aUnqPath, this methods returns a XInputStream which reads from the open file. 676 // 677 678 679 uno::Reference< io::XInputStream > SAL_CALL 680 shell::open( sal_Int32 CommandId, 681 const rtl::OUString& aUnqPath, 682 sal_Bool bLock ) 683 throw() 684 { 685 XInputStream_impl* xInputStream = new XInputStream_impl( this, aUnqPath, bLock ); // from filinpstr.hxx 686 687 sal_Int32 ErrorCode = xInputStream->CtorSuccess(); 688 689 if( ErrorCode != TASKHANDLER_NO_ERROR ) 690 { 691 installError( CommandId, 692 ErrorCode, 693 xInputStream->getMinorError() ); 694 695 delete xInputStream; 696 xInputStream = 0; 697 } 698 699 return uno::Reference< io::XInputStream >( xInputStream ); 700 } 701 702 703 704 705 /*********************************************************************************/ 706 /* */ 707 /* open for read/write access-Implementation */ 708 /* */ 709 /*********************************************************************************/ 710 // 711 // Given a file URL aUnqPath, this methods returns a XStream which can be used 712 // to read and write from/to the file. 713 // 714 715 716 uno::Reference< io::XStream > SAL_CALL 717 shell::open_rw( sal_Int32 CommandId, 718 const rtl::OUString& aUnqPath, 719 sal_Bool bLock ) 720 throw() 721 { 722 XStream_impl* xStream = new XStream_impl( this, aUnqPath, bLock ); // from filstr.hxx 723 724 sal_Int32 ErrorCode = xStream->CtorSuccess(); 725 726 if( ErrorCode != TASKHANDLER_NO_ERROR ) 727 { 728 installError( CommandId, 729 ErrorCode, 730 xStream->getMinorError() ); 731 732 delete xStream; 733 xStream = 0; 734 } 735 return uno::Reference< io::XStream >( xStream ); 736 } 737 738 739 740 /*********************************************************************************/ 741 /* */ 742 /* ls-Implementation */ 743 /* */ 744 /*********************************************************************************/ 745 // 746 // This method returns the result set containing the the children of the directory belonging 747 // to file URL aUnqPath 748 // 749 750 751 uno::Reference< XDynamicResultSet > SAL_CALL 752 shell::ls( sal_Int32 CommandId, 753 const rtl::OUString& aUnqPath, 754 const sal_Int32 OpenMode, 755 const uno::Sequence< beans::Property >& seq, 756 const uno::Sequence< NumberedSortingInfo >& seqSort ) 757 throw() 758 { 759 XResultSet_impl* p = new XResultSet_impl( this,aUnqPath,OpenMode,seq,seqSort ); 760 761 sal_Int32 ErrorCode = p->CtorSuccess(); 762 763 if( ErrorCode != TASKHANDLER_NO_ERROR ) 764 { 765 installError( CommandId, 766 ErrorCode, 767 p->getMinorError() ); 768 769 delete p; 770 p = 0; 771 } 772 773 return uno::Reference< XDynamicResultSet > ( p ); 774 } 775 776 777 778 779 /*********************************************************************************/ 780 /* */ 781 /* info_c implementation */ 782 /* */ 783 /*********************************************************************************/ 784 // Info for commands 785 786 uno::Reference< XCommandInfo > SAL_CALL 787 shell::info_c() 788 throw() 789 { 790 XCommandInfo_impl* p = new XCommandInfo_impl( this ); 791 return uno::Reference< XCommandInfo >( p ); 792 } 793 794 795 796 797 /*********************************************************************************/ 798 /* */ 799 /* info_p-Implementation */ 800 /* */ 801 /*********************************************************************************/ 802 // Info for the properties 803 804 uno::Reference< beans::XPropertySetInfo > SAL_CALL 805 shell::info_p( const rtl::OUString& aUnqPath ) 806 throw() 807 { 808 osl::MutexGuard aGuard( m_aMutex ); 809 XPropertySetInfo_impl* p = new XPropertySetInfo_impl( this,aUnqPath ); 810 return uno::Reference< beans::XPropertySetInfo >( p ); 811 } 812 813 814 815 816 /*********************************************************************************/ 817 /* */ 818 /* setv-Implementation */ 819 /* */ 820 /*********************************************************************************/ 821 // 822 // Sets the values of the properties belonging to fileURL aUnqPath 823 // 824 825 826 uno::Sequence< uno::Any > SAL_CALL 827 shell::setv( const rtl::OUString& aUnqPath, 828 const uno::Sequence< beans::PropertyValue >& values ) 829 throw() 830 { 831 osl::MutexGuard aGuard( m_aMutex ); 832 833 sal_Int32 propChanged = 0; 834 uno::Sequence< uno::Any > ret( values.getLength() ); 835 uno::Sequence< beans::PropertyChangeEvent > seqChanged( values.getLength() ); 836 837 shell::ContentMap::iterator it = m_aContent.find( aUnqPath ); 838 PropertySet& properties = *( it->second.properties ); 839 shell::PropertySet::iterator it1; 840 uno::Any aAny; 841 842 for( sal_Int32 i = 0; i < values.getLength(); ++i ) 843 { 844 MyProperty toset( values[i].Name ); 845 it1 = properties.find( toset ); 846 if( it1 == properties.end() ) 847 { 848 ret[i] <<= beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 849 continue; 850 } 851 852 aAny = it1->getValue(); 853 if( aAny == values[i].Value ) 854 continue; // nothing needs to be changed 855 856 if( it1->getAttributes() & beans::PropertyAttribute::READONLY ) 857 { 858 ret[i] <<= lang::IllegalAccessException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 859 continue; 860 } 861 862 seqChanged[ propChanged ].PropertyName = values[i].Name; 863 seqChanged[ propChanged ].PropertyHandle = -1; 864 seqChanged[ propChanged ].Further = false; 865 seqChanged[ propChanged ].OldValue <<= aAny; 866 seqChanged[ propChanged++ ].NewValue = values[i].Value; 867 868 it1->setValue( values[i].Value ); // Put the new value into the local cash 869 870 if( ! it1->IsNative() ) 871 { 872 // Also put logical properties into storage 873 if( !it->second.xS.is() ) 874 load( it,true ); 875 876 if( ( values[i].Name == ContentType ) && 877 it1->getState() == beans::PropertyState_DEFAULT_VALUE ) 878 { // Special logic for ContentType 879 // 09.07.01: Not reached anymore, because ContentType is readonly 880 it1->setState( beans::PropertyState_DIRECT_VALUE ); 881 it->second.xC->addProperty( values[i].Name, 882 beans::PropertyAttribute::MAYBEVOID, 883 values[i].Value ); 884 } 885 886 try 887 { 888 it->second.xS->setPropertyValue( values[i].Name,values[i].Value ); 889 } 890 catch( const uno::Exception& e ) 891 { 892 --propChanged; // unsuccessful setting 893 ret[i] <<= e; 894 } 895 } 896 else 897 { 898 // native properties 899 // Setting of physical file properties 900 if( values[i].Name == Size ) 901 { 902 sal_Int64 newSize = 0; 903 if( values[i].Value >>= newSize ) 904 { // valid value for the size 905 osl::File aFile(aUnqPath); 906 bool err = 907 aFile.open(OpenFlag_Write) != osl::FileBase::E_None || 908 aFile.setSize(sal_uInt64(newSize)) != osl::FileBase::E_None || 909 aFile.close() != osl::FileBase::E_None; 910 911 if( err ) 912 { 913 --propChanged; // unsuccessful setting 914 uno::Sequence< uno::Any > names( 1 ); 915 ret[0] <<= beans::PropertyValue( 916 rtl::OUString::createFromAscii("Uri"), -1, 917 uno::makeAny(aUnqPath), 918 beans::PropertyState_DIRECT_VALUE); 919 IOErrorCode ioError(IOErrorCode_GENERAL); 920 ret[i] <<= InteractiveAugmentedIOException( 921 rtl::OUString(), 922 0, 923 task::InteractionClassification_ERROR, 924 ioError, 925 names ); 926 } 927 } 928 else 929 ret[i] <<= beans::IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 930 } 931 else if(values[i].Name == IsReadOnly || 932 values[i].Name == IsHidden) 933 { 934 sal_Bool value = sal_False; 935 if( values[i].Value >>= value ) 936 { 937 osl::DirectoryItem aDirItem; 938 osl::FileBase::RC err = 939 osl::DirectoryItem::get(aUnqPath,aDirItem); 940 sal_uInt64 nAttributes(0); 941 if(err == osl::FileBase::E_None) 942 { 943 osl::FileStatus aFileStatus(FileStatusMask_Attributes); 944 err = aDirItem.getFileStatus(aFileStatus); 945 if(err == osl::FileBase::E_None && 946 aFileStatus.isValid(FileStatusMask_Attributes)) 947 nAttributes = aFileStatus.getAttributes(); 948 } 949 // now we have the attributes provided all went well. 950 if(err == osl::FileBase::E_None) { 951 if(values[i].Name == IsReadOnly) 952 { 953 nAttributes &= ~(Attribute_OwnWrite | 954 Attribute_GrpWrite | 955 Attribute_OthWrite | 956 Attribute_ReadOnly); 957 if(value) 958 nAttributes |= Attribute_ReadOnly; 959 else 960 nAttributes |= ( 961 Attribute_OwnWrite | 962 Attribute_GrpWrite | 963 Attribute_OthWrite); 964 } 965 else if(values[i].Name == IsHidden) 966 { 967 nAttributes &= ~(Attribute_Hidden); 968 if(value) 969 nAttributes |= Attribute_Hidden; 970 } 971 err = osl::File::setAttributes( 972 aUnqPath,nAttributes); 973 } 974 975 if( err != osl::FileBase::E_None ) 976 { 977 --propChanged; // unsuccessful setting 978 uno::Sequence< uno::Any > names( 1 ); 979 names[0] <<= beans::PropertyValue( 980 rtl::OUString::createFromAscii("Uri"), -1, 981 uno::makeAny(aUnqPath), 982 beans::PropertyState_DIRECT_VALUE); 983 IOErrorCode ioError; 984 switch( err ) 985 { 986 case osl::FileBase::E_NOMEM: 987 // not enough memory for allocating structures <br> 988 ioError = IOErrorCode_OUT_OF_MEMORY; 989 break; 990 case osl::FileBase::E_INVAL: 991 // the format of the parameters was not valid<p> 992 ioError = IOErrorCode_INVALID_PARAMETER; 993 break; 994 case osl::FileBase::E_NAMETOOLONG: 995 // File name too long<br> 996 ioError = IOErrorCode_NAME_TOO_LONG; 997 break; 998 case osl::FileBase::E_NOENT: 999 // No such file or directory<br> 1000 case osl::FileBase::E_NOLINK: 1001 // Link has been severed<br> 1002 ioError = IOErrorCode_NOT_EXISTING; 1003 break; 1004 case osl::FileBase::E_ROFS: 1005 // #i4735# handle ROFS transparently 1006 // as ACCESS_DENIED 1007 case osl::FileBase::E_PERM: 1008 case osl::FileBase::E_ACCES: 1009 // permission denied<br> 1010 ioError = IOErrorCode_ACCESS_DENIED; 1011 break; 1012 case osl::FileBase::E_LOOP: 1013 // Too many symbolic links encountered<br> 1014 case osl::FileBase::E_FAULT: 1015 // Bad address<br> 1016 case osl::FileBase::E_IO: 1017 // I/O error<br> 1018 case osl::FileBase::E_NOSYS: 1019 // Function not implemented<br> 1020 case osl::FileBase::E_MULTIHOP: 1021 // Multihop attempted<br> 1022 case osl::FileBase::E_INTR: 1023 // function call was interrupted<p> 1024 default: 1025 ioError = IOErrorCode_GENERAL; 1026 break; 1027 } 1028 ret[i] <<= InteractiveAugmentedIOException( 1029 rtl::OUString(), 1030 0, 1031 task::InteractionClassification_ERROR, 1032 ioError, 1033 names ); 1034 } 1035 } 1036 else 1037 ret[i] <<= beans::IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 1038 } 1039 } 1040 } // end for 1041 1042 if( propChanged ) 1043 { 1044 seqChanged.realloc( propChanged ); 1045 notifyPropertyChanges( getPropertyChangeNotifier( aUnqPath ),seqChanged ); 1046 } 1047 1048 return ret; 1049 } 1050 1051 /*********************************************************************************/ 1052 /* */ 1053 /* getv-Implementation */ 1054 /* */ 1055 /*********************************************************************************/ 1056 // 1057 // Reads the values of the properties belonging to fileURL aUnqPath; 1058 // Returns an XRow object containing the values in the requested order. 1059 // 1060 1061 1062 uno::Reference< sdbc::XRow > SAL_CALL 1063 shell::getv( sal_Int32 CommandId, 1064 const rtl::OUString& aUnqPath, 1065 const uno::Sequence< beans::Property >& properties ) 1066 throw() 1067 { 1068 uno::Sequence< uno::Any > seq( properties.getLength() ); 1069 1070 sal_Int32 n_Mask; 1071 getMaskFromProperties( n_Mask,properties ); 1072 osl::FileStatus aFileStatus( n_Mask ); 1073 1074 osl::DirectoryItem aDirItem; 1075 osl::FileBase::RC nError1 = osl::DirectoryItem::get( aUnqPath,aDirItem ); 1076 if( nError1 != osl::FileBase::E_None ) 1077 installError(CommandId, 1078 TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED 1079 nError1); 1080 1081 osl::FileBase::RC nError2 = aDirItem.getFileStatus( aFileStatus ); 1082 if( nError1 == osl::FileBase::E_None && 1083 nError2 != osl::FileBase::E_None ) 1084 installError(CommandId, 1085 TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED 1086 nError2); 1087 1088 { 1089 osl::MutexGuard aGuard( m_aMutex ); 1090 1091 shell::ContentMap::iterator it = m_aContent.find( aUnqPath ); 1092 commit( it,aFileStatus ); 1093 1094 shell::PropertySet::iterator it1; 1095 PropertySet& propset = *(it->second.properties); 1096 1097 for( sal_Int32 i = 0; i < seq.getLength(); ++i ) 1098 { 1099 MyProperty readProp( properties[i].Name ); 1100 it1 = propset.find( readProp ); 1101 if( it1 == propset.end() ) 1102 seq[i] = uno::Any(); 1103 else 1104 seq[i] = it1->getValue(); 1105 } 1106 } 1107 1108 XRow_impl* p = new XRow_impl( this,seq ); 1109 return uno::Reference< sdbc::XRow >( p ); 1110 } 1111 1112 1113 /********************************************************************************/ 1114 /* */ 1115 /* transfer-commandos */ 1116 /* */ 1117 /********************************************************************************/ 1118 1119 1120 /********************************************************************************/ 1121 /* */ 1122 /* move-implementation */ 1123 /* */ 1124 /********************************************************************************/ 1125 // 1126 // Moves the content belonging to fileURL srcUnqPath to fileURL dstUnqPath. 1127 // 1128 1129 void SAL_CALL 1130 shell::move( sal_Int32 CommandId, 1131 const rtl::OUString srcUnqPath, 1132 const rtl::OUString dstUnqPathIn, 1133 const sal_Int32 NameClash ) 1134 throw() 1135 { 1136 // --> #i88446# Method notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); crashes if 1137 // srcUnqPath and dstUnqPathIn are equal 1138 if( srcUnqPath == dstUnqPathIn ) 1139 return; 1140 // <-- 1141 // 1142 osl::FileBase::RC nError; 1143 rtl::OUString dstUnqPath( dstUnqPathIn ); 1144 1145 switch( NameClash ) 1146 { 1147 case NameClash::KEEP: 1148 { 1149 nError = osl_File_move( srcUnqPath,dstUnqPath,true ); 1150 if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST ) 1151 { 1152 installError( CommandId, 1153 TASKHANDLING_KEEPERROR_FOR_MOVE, 1154 nError ); 1155 return; 1156 } 1157 break; 1158 } 1159 case NameClash::OVERWRITE: 1160 { 1161 // stat to determine whether we have a symlink 1162 rtl::OUString targetPath(dstUnqPath); 1163 1164 osl::FileStatus aStatus(FileStatusMask_Type|FileStatusMask_LinkTargetURL); 1165 osl::DirectoryItem aItem; 1166 osl::DirectoryItem::get(dstUnqPath,aItem); 1167 aItem.getFileStatus(aStatus); 1168 1169 if( aStatus.isValid(FileStatusMask_Type) && 1170 aStatus.isValid(FileStatusMask_LinkTargetURL) && 1171 aStatus.getFileType() == osl::FileStatus::Link ) 1172 targetPath = aStatus.getLinkTargetURL(); 1173 1174 // Will do nothing if file does not exist. 1175 osl::File::remove( targetPath ); 1176 1177 nError = osl_File_move( srcUnqPath,targetPath ); 1178 if( nError != osl::FileBase::E_None ) 1179 { 1180 installError( CommandId, 1181 TASKHANDLING_OVERWRITE_FOR_MOVE, 1182 nError ); 1183 return; 1184 } 1185 break; 1186 } 1187 case NameClash::RENAME: 1188 { 1189 rtl::OUString newDstUnqPath; 1190 nError = osl_File_move( srcUnqPath,dstUnqPath,true ); 1191 if( nError == osl::FileBase::E_EXIST ) 1192 { 1193 // "invent" a new valid title. 1194 1195 sal_Int32 nPos = -1; 1196 sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' ); 1197 sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' ); 1198 if( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment 1199 && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot 1200 nPos = nLastDot; 1201 else 1202 nPos = dstUnqPath.getLength(); 1203 1204 sal_Int32 nTry = 0; 1205 1206 do 1207 { 1208 newDstUnqPath = dstUnqPath; 1209 1210 rtl::OUString aPostFix( rtl::OUString::createFromAscii( "_" ) ); 1211 aPostFix += rtl::OUString::valueOf( ++nTry ); 1212 1213 newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostFix ); 1214 1215 nError = osl_File_move( srcUnqPath,newDstUnqPath,true ); 1216 } 1217 while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) ); 1218 } 1219 1220 if( nError == osl::FileBase::E_EXIST ) 1221 { 1222 installError( CommandId, 1223 TASKHANDLING_RENAME_FOR_MOVE ); 1224 return; 1225 } 1226 else if( nError != osl::FileBase::E_None ) 1227 { 1228 installError( CommandId, 1229 TASKHANDLING_RENAMEMOVE_FOR_MOVE, 1230 nError ); 1231 return; 1232 } 1233 else 1234 dstUnqPath = newDstUnqPath; 1235 1236 break; 1237 } 1238 case NameClash::ERROR: 1239 { 1240 nError = osl_File_move( srcUnqPath,dstUnqPath,true ); 1241 if( nError == osl::FileBase::E_EXIST ) 1242 { 1243 installError( CommandId, 1244 TASKHANDLING_NAMECLASH_FOR_MOVE ); 1245 return; 1246 } 1247 else if( nError != osl::FileBase::E_None ) 1248 { 1249 installError( CommandId, 1250 TASKHANDLING_NAMECLASHMOVE_FOR_MOVE, 1251 nError ); 1252 return; 1253 } 1254 break; 1255 } 1256 case NameClash::ASK: 1257 default: 1258 { 1259 nError = osl_File_move( srcUnqPath,dstUnqPath,true ); 1260 if( nError == osl::FileBase::E_EXIST ) 1261 { 1262 installError( CommandId, 1263 TASKHANDLING_NAMECLASHSUPPORT_FOR_MOVE, 1264 NameClash::ASK); 1265 return; 1266 } 1267 } 1268 break; 1269 } 1270 1271 // Determine, whether we have moved a file or a folder 1272 osl::DirectoryItem aItem; 1273 nError = osl::DirectoryItem::get( dstUnqPath,aItem ); 1274 if( nError != osl::FileBase::E_None ) 1275 { 1276 installError( CommandId, 1277 TASKHANDLING_TRANSFER_BY_MOVE_SOURCE, 1278 nError ); 1279 return; 1280 } 1281 osl::FileStatus aStatus( FileStatusMask_Type ); 1282 nError = aItem.getFileStatus( aStatus ); 1283 if( nError != osl::FileBase::E_None || ! aStatus.isValid( FileStatusMask_Type ) ) 1284 { 1285 installError( CommandId, 1286 TASKHANDLING_TRANSFER_BY_MOVE_SOURCESTAT, 1287 nError ); 1288 return; 1289 } 1290 sal_Bool isDocument = ( aStatus.getFileType() == osl::FileStatus::Regular ); 1291 1292 1293 copyPersistentSet( srcUnqPath,dstUnqPath,!isDocument ); 1294 1295 rtl::OUString aDstParent = getParentName( dstUnqPath ); 1296 rtl::OUString aDstTitle = getTitle( dstUnqPath ); 1297 1298 rtl::OUString aSrcParent = getParentName( srcUnqPath ); 1299 rtl::OUString aSrcTitle = getTitle( srcUnqPath ); 1300 1301 notifyInsert( getContentEventListeners( aDstParent ),dstUnqPath ); 1302 if( aDstParent != aSrcParent ) 1303 notifyContentRemoved( getContentEventListeners( aSrcParent ),srcUnqPath ); 1304 1305 notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); 1306 erasePersistentSet( srcUnqPath,!isDocument ); 1307 } 1308 1309 1310 1311 /********************************************************************************/ 1312 /* */ 1313 /* copy-implementation */ 1314 /* */ 1315 /********************************************************************************/ 1316 // 1317 // Copies the content belonging to fileURL srcUnqPath to fileURL dstUnqPath ( files and directories ) 1318 // 1319 1320 namespace { 1321 1322 bool getType( 1323 TaskManager & task, sal_Int32 id, rtl::OUString const & fileUrl, 1324 osl::DirectoryItem * item, osl::FileStatus::Type * type) 1325 { 1326 OSL_ASSERT(item != 0 && type != 0); 1327 osl::FileBase::RC err = osl::DirectoryItem::get(fileUrl, *item); 1328 if (err != osl::FileBase::E_None) { 1329 task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCE, err); 1330 return false; 1331 } 1332 osl::FileStatus stat(FileStatusMask_Type); 1333 err = item->getFileStatus(stat); 1334 if (err != osl::FileBase::E_None) { 1335 task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, err); 1336 return false; 1337 } 1338 *type = stat.getFileType(); 1339 return true; 1340 } 1341 1342 } 1343 1344 void SAL_CALL 1345 shell::copy( 1346 sal_Int32 CommandId, 1347 const rtl::OUString srcUnqPath, 1348 const rtl::OUString dstUnqPathIn, 1349 sal_Int32 NameClash ) 1350 throw() 1351 { 1352 osl::FileBase::RC nError; 1353 rtl::OUString dstUnqPath( dstUnqPathIn ); 1354 1355 // Resolve symbolic links within the source path. If srcUnqPath denotes a 1356 // symbolic link (targeting either a file or a folder), the contents of the 1357 // target is copied (recursively, in the case of a folder). However, if 1358 // recursively copying the contents of a folder causes a symbolic link to be 1359 // copied, the symbolic link itself is copied. 1360 osl::DirectoryItem item; 1361 osl::FileStatus::Type type; 1362 if (!getType(*this, CommandId, srcUnqPath, &item, &type)) { 1363 return; 1364 } 1365 rtl::OUString rslvdSrcUnqPath; 1366 if (type == osl::FileStatus::Link) { 1367 osl::FileStatus stat(FileStatusMask_LinkTargetURL); 1368 nError = item.getFileStatus(stat); 1369 if (nError != osl::FileBase::E_None) { 1370 installError( 1371 CommandId, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, nError); 1372 return; 1373 } 1374 rslvdSrcUnqPath = stat.getLinkTargetURL(); 1375 if (!getType(*this, CommandId, srcUnqPath, &item, &type)) { 1376 return; 1377 } 1378 } else { 1379 rslvdSrcUnqPath = srcUnqPath; 1380 } 1381 1382 sal_Bool isDocument 1383 = type != osl::FileStatus::Directory && type != osl::FileStatus::Volume; 1384 sal_Int32 IsWhat = isDocument ? -1 : 1; 1385 1386 switch( NameClash ) 1387 { 1388 case NameClash::KEEP: 1389 { 1390 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); 1391 if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST ) 1392 { 1393 installError( CommandId, 1394 TASKHANDLING_KEEPERROR_FOR_COPY, 1395 nError ); 1396 return; 1397 } 1398 break; 1399 } 1400 case NameClash::OVERWRITE: 1401 { 1402 // remove (..., MustExist = sal_False). 1403 remove( CommandId, dstUnqPath, IsWhat, sal_False ); 1404 1405 // copy. 1406 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,false ); 1407 if( nError != osl::FileBase::E_None ) 1408 { 1409 installError( CommandId, 1410 TASKHANDLING_OVERWRITE_FOR_COPY, 1411 nError ); 1412 return; 1413 } 1414 break; 1415 } 1416 case NameClash::RENAME: 1417 { 1418 rtl::OUString newDstUnqPath; 1419 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); 1420 1421 if( nError == osl::FileBase::E_EXIST ) 1422 { 1423 // "invent" a new valid title. 1424 1425 sal_Int32 nPos = -1; 1426 sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' ); 1427 sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' ); 1428 if ( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment 1429 && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot 1430 nPos = nLastDot; 1431 else 1432 nPos = dstUnqPath.getLength(); 1433 1434 sal_Int32 nTry = 0; 1435 1436 do 1437 { 1438 newDstUnqPath = dstUnqPath; 1439 1440 rtl::OUString aPostFix( rtl::OUString::createFromAscii( "_" ) ); 1441 aPostFix += rtl::OUString::valueOf( ++nTry ); 1442 1443 newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostFix ); 1444 1445 nError = copy_recursive( rslvdSrcUnqPath,newDstUnqPath,IsWhat,true ); 1446 } 1447 while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) ); 1448 } 1449 1450 if( nError == osl::FileBase::E_EXIST ) 1451 { 1452 installError( CommandId, 1453 TASKHANDLING_RENAME_FOR_COPY ); 1454 return; 1455 } 1456 else if( nError != osl::FileBase::E_None ) 1457 { 1458 installError( CommandId, 1459 TASKHANDLING_RENAMEMOVE_FOR_COPY, 1460 nError ); 1461 return; 1462 } 1463 else 1464 dstUnqPath = newDstUnqPath; 1465 1466 break; 1467 } 1468 case NameClash::ERROR: 1469 { 1470 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); 1471 1472 if( nError == osl::FileBase::E_EXIST ) 1473 { 1474 installError( CommandId, 1475 TASKHANDLING_NAMECLASH_FOR_COPY ); 1476 return; 1477 } 1478 else if( nError != osl::FileBase::E_None ) 1479 { 1480 installError( CommandId, 1481 TASKHANDLING_NAMECLASHMOVE_FOR_COPY, 1482 nError ); 1483 return; 1484 } 1485 break; 1486 } 1487 case NameClash::ASK: 1488 default: 1489 { 1490 nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); 1491 1492 if( nError == osl::FileBase::E_EXIST ) 1493 { 1494 installError( CommandId, 1495 TASKHANDLING_NAMECLASHSUPPORT_FOR_COPY, 1496 NameClash); 1497 return; 1498 } 1499 break; 1500 } 1501 } 1502 1503 copyPersistentSet( srcUnqPath,dstUnqPath, !isDocument ); 1504 notifyInsert( getContentEventListeners( getParentName( dstUnqPath ) ),dstUnqPath ); 1505 } 1506 1507 1508 1509 /********************************************************************************/ 1510 /* */ 1511 /* remove-implementation */ 1512 /* */ 1513 /********************************************************************************/ 1514 // 1515 // Deletes the content belonging to fileURL aUnqPath( recursively in case of directory ) 1516 // Return: success of operation 1517 // 1518 1519 1520 sal_Bool SAL_CALL 1521 shell::remove( sal_Int32 CommandId, 1522 const rtl::OUString& aUnqPath, 1523 sal_Int32 IsWhat, 1524 sal_Bool MustExist ) 1525 throw() 1526 { 1527 sal_Int32 nMask = FileStatusMask_Type | FileStatusMask_FileURL; 1528 1529 osl::DirectoryItem aItem; 1530 osl::FileStatus aStatus( nMask ); 1531 osl::FileBase::RC nError; 1532 1533 if( IsWhat == 0 ) // Determine whether we are removing a directory or a file 1534 { 1535 nError = osl::DirectoryItem::get( aUnqPath, aItem ); 1536 if( nError != osl::FileBase::E_None ) 1537 { 1538 if (MustExist) 1539 { 1540 installError( CommandId, 1541 TASKHANDLING_NOSUCHFILEORDIR_FOR_REMOVE, 1542 nError ); 1543 } 1544 return (!MustExist); 1545 } 1546 1547 nError = aItem.getFileStatus( aStatus ); 1548 if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) ) 1549 { 1550 installError( CommandId, 1551 TASKHANDLING_VALIDFILESTATUS_FOR_REMOVE, 1552 nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR ); 1553 return sal_False; 1554 } 1555 1556 if( aStatus.getFileType() == osl::FileStatus::Regular || 1557 aStatus.getFileType() == osl::FileStatus::Link ) 1558 IsWhat = -1; // RemoveFile 1559 else if( aStatus.getFileType() == osl::FileStatus::Directory || 1560 aStatus.getFileType() == osl::FileStatus::Volume ) 1561 IsWhat = +1; // RemoveDirectory 1562 } 1563 1564 1565 if( IsWhat == -1 ) // Removing a file 1566 { 1567 nError = osl::File::remove( aUnqPath ); 1568 if( nError != osl::FileBase::E_None ) 1569 { 1570 if (MustExist) 1571 { 1572 installError( CommandId, 1573 TASKHANDLING_DELETEFILE_FOR_REMOVE, 1574 nError ); 1575 } 1576 return (!MustExist); 1577 } 1578 else 1579 { 1580 notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) ); 1581 erasePersistentSet( aUnqPath ); // Removes from XPersistentPropertySet 1582 } 1583 } 1584 else if( IsWhat == +1 ) // Removing a directory 1585 { 1586 osl::Directory aDirectory( aUnqPath ); 1587 1588 nError = aDirectory.open(); 1589 if( nError != osl::FileBase::E_None ) 1590 { 1591 if (MustExist) 1592 { 1593 installError( CommandId, 1594 TASKHANDLING_OPENDIRECTORY_FOR_REMOVE, 1595 nError ); 1596 } 1597 return (!MustExist); 1598 } 1599 1600 sal_Bool whileSuccess = sal_True; 1601 sal_Int32 recurse = 0; 1602 rtl::OUString name; 1603 1604 nError = aDirectory.getNextItem( aItem ); 1605 while( nError == osl::FileBase::E_None ) 1606 { 1607 nError = aItem.getFileStatus( aStatus ); 1608 if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) ) 1609 { 1610 installError( CommandId, 1611 TASKHANDLING_VALIDFILESTATUSWHILE_FOR_REMOVE, 1612 nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR ); 1613 whileSuccess = sal_False; 1614 break; 1615 } 1616 1617 if( aStatus.getFileType() == osl::FileStatus::Regular || 1618 aStatus.getFileType() == osl::FileStatus::Link ) 1619 recurse = -1; 1620 else if( aStatus.getFileType() == osl::FileStatus::Directory || 1621 aStatus.getFileType() == osl::FileStatus::Volume ) 1622 recurse = +1; 1623 1624 name = aStatus.getFileURL(); 1625 whileSuccess = remove( 1626 CommandId, name, recurse, MustExist ); 1627 if( !whileSuccess ) 1628 break; 1629 1630 nError = aDirectory.getNextItem( aItem ); 1631 } 1632 1633 aDirectory.close(); 1634 1635 if( ! whileSuccess ) 1636 return sal_False; // error code is installed 1637 1638 if( nError != osl::FileBase::E_NOENT ) 1639 { 1640 installError( CommandId, 1641 TASKHANDLING_DIRECTORYEXHAUSTED_FOR_REMOVE, 1642 nError ); 1643 return sal_False; 1644 } 1645 1646 nError = osl::Directory::remove( aUnqPath ); 1647 if( nError != osl::FileBase::E_None ) 1648 { 1649 if (MustExist) 1650 { 1651 installError( CommandId, 1652 TASKHANDLING_DELETEDIRECTORY_FOR_REMOVE, 1653 nError ); 1654 } 1655 return (!MustExist); 1656 } 1657 else 1658 { 1659 notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) ); 1660 erasePersistentSet( aUnqPath ); 1661 } 1662 } 1663 else // Don't know what to remove 1664 { 1665 installError( CommandId, 1666 TASKHANDLING_FILETYPE_FOR_REMOVE ); 1667 return sal_False; 1668 } 1669 1670 return sal_True; 1671 } 1672 1673 1674 /********************************************************************************/ 1675 /* */ 1676 /* mkdir-implementation */ 1677 /* */ 1678 /********************************************************************************/ 1679 // 1680 // Creates new directory with given URL, recursively if necessary 1681 // Return:: success of operation 1682 // 1683 1684 sal_Bool SAL_CALL 1685 shell::mkdir( sal_Int32 CommandId, 1686 const rtl::OUString& rUnqPath, 1687 sal_Bool OverWrite ) 1688 throw() 1689 { 1690 rtl::OUString aUnqPath; 1691 1692 // remove trailing slash 1693 if ( rUnqPath[ rUnqPath.getLength() - 1 ] == sal_Unicode( '/' ) ) 1694 aUnqPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 ); 1695 else 1696 aUnqPath = rUnqPath; 1697 1698 osl::FileBase::RC nError = osl::Directory::create( aUnqPath ); 1699 1700 switch ( nError ) 1701 { 1702 case osl::FileBase::E_EXIST: // Directory cannot be overwritten 1703 { 1704 if( !OverWrite ) 1705 { 1706 installError( CommandId, 1707 TASKHANDLING_FOLDER_EXISTS_MKDIR ); 1708 return sal_False; 1709 } 1710 else 1711 return sal_True; 1712 } 1713 case osl::FileBase::E_INVAL: 1714 { 1715 installError(CommandId, 1716 TASKHANDLING_INVALID_NAME_MKDIR); 1717 return sal_False; 1718 } 1719 case osl::FileBase::E_None: 1720 { 1721 rtl::OUString aPrtPath = getParentName( aUnqPath ); 1722 notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath ); 1723 return sal_True; 1724 } 1725 default: 1726 return ensuredir( 1727 CommandId, 1728 aUnqPath, 1729 TASKHANDLING_CREATEDIRECTORY_MKDIR ); 1730 } 1731 } 1732 1733 1734 /********************************************************************************/ 1735 /* */ 1736 /* mkfil-implementation */ 1737 /* */ 1738 /********************************************************************************/ 1739 // 1740 // Creates new file with given URL. 1741 // The content of aInputStream becomes the content of the file 1742 // Return:: success of operation 1743 // 1744 1745 sal_Bool SAL_CALL 1746 shell::mkfil( sal_Int32 CommandId, 1747 const rtl::OUString& aUnqPath, 1748 sal_Bool Overwrite, 1749 const uno::Reference< io::XInputStream >& aInputStream ) 1750 throw() 1751 { 1752 // return value unimportant 1753 sal_Bool bSuccess = write( CommandId, 1754 aUnqPath, 1755 Overwrite, 1756 aInputStream ); 1757 if ( bSuccess ) 1758 { 1759 rtl::OUString aPrtPath = getParentName( aUnqPath ); 1760 notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath ); 1761 } 1762 return bSuccess; 1763 } 1764 1765 1766 /********************************************************************************/ 1767 /* */ 1768 /* write-implementation */ 1769 /* */ 1770 /********************************************************************************/ 1771 // 1772 // writes to the file with given URL. 1773 // The content of aInputStream becomes the content of the file 1774 // Return:: success of operation 1775 // 1776 1777 sal_Bool SAL_CALL 1778 shell::write( sal_Int32 CommandId, 1779 const rtl::OUString& aUnqPath, 1780 sal_Bool OverWrite, 1781 const uno::Reference< io::XInputStream >& aInputStream ) 1782 throw() 1783 { 1784 if( ! aInputStream.is() ) 1785 { 1786 installError( CommandId, 1787 TASKHANDLING_INPUTSTREAM_FOR_WRITE ); 1788 return sal_False; 1789 } 1790 1791 // Create parent path, if necessary. 1792 if ( ! ensuredir( CommandId, 1793 getParentName( aUnqPath ), 1794 TASKHANDLING_ENSUREDIR_FOR_WRITE ) ) 1795 return sal_False; 1796 1797 osl::FileBase::RC err; 1798 osl::File aFile( aUnqPath ); 1799 1800 if( OverWrite ) 1801 { 1802 err = aFile.open( OpenFlag_Write | OpenFlag_Create ); 1803 1804 if( err != osl::FileBase::E_None ) 1805 { 1806 aFile.close(); 1807 err = aFile.open( OpenFlag_Write ); 1808 1809 if( err != osl::FileBase::E_None ) 1810 { 1811 installError( CommandId, 1812 TASKHANDLING_NO_OPEN_FILE_FOR_OVERWRITE, 1813 err ); 1814 return sal_False; 1815 } 1816 1817 // the existing file was just opened and should be overwritten now, 1818 // truncate it first 1819 1820 err = aFile.setSize( 0 ); 1821 if( err != osl::FileBase::E_None ) 1822 { 1823 installError( CommandId, 1824 TASKHANDLING_FILESIZE_FOR_WRITE, 1825 err ); 1826 return sal_False; 1827 } 1828 } 1829 } 1830 else 1831 { 1832 err = aFile.open( OpenFlag_Read | OpenFlag_NoLock ); 1833 if( err == osl::FileBase::E_None ) // The file exists and shall not be overwritten 1834 { 1835 installError( CommandId, 1836 TASKHANDLING_NOREPLACE_FOR_WRITE, // Now an exception 1837 err ); 1838 1839 aFile.close(); 1840 return sal_False; 1841 } 1842 1843 // as a temporary solution the creation does not lock the file at all 1844 // in future it should be possible to create the file without lock explicitly 1845 err = aFile.open( OpenFlag_Write | OpenFlag_Create | OpenFlag_NoLock ); 1846 1847 if( err != osl::FileBase::E_None ) 1848 { 1849 aFile.close(); 1850 installError( CommandId, 1851 TASKHANDLING_NO_OPEN_FILE_FOR_WRITE, 1852 err ); 1853 return sal_False; 1854 } 1855 } 1856 1857 sal_Bool bSuccess = sal_True; 1858 1859 sal_uInt64 nWrittenBytes; 1860 sal_Int32 nReadBytes = 0, nRequestedBytes = 32768 /*32k*/; 1861 uno::Sequence< sal_Int8 > seq( nRequestedBytes ); 1862 1863 do 1864 { 1865 try 1866 { 1867 nReadBytes = aInputStream->readBytes( seq, 1868 nRequestedBytes ); 1869 } 1870 catch( const io::NotConnectedException& ) 1871 { 1872 installError( CommandId, 1873 TASKHANDLING_NOTCONNECTED_FOR_WRITE ); 1874 bSuccess = sal_False; 1875 break; 1876 } 1877 catch( const io::BufferSizeExceededException& ) 1878 { 1879 installError( CommandId, 1880 TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_WRITE ); 1881 bSuccess = sal_False; 1882 break; 1883 } 1884 catch( const io::IOException& ) 1885 { 1886 installError( CommandId, 1887 TASKHANDLING_IOEXCEPTION_FOR_WRITE ); 1888 bSuccess = sal_False; 1889 break; 1890 } 1891 1892 if( nReadBytes ) 1893 { 1894 const sal_Int8* p = seq.getConstArray(); 1895 1896 err = aFile.write( ((void*)(p)), 1897 sal_uInt64( nReadBytes ), 1898 nWrittenBytes ); 1899 1900 if( err != osl::FileBase::E_None ) 1901 { 1902 installError( CommandId, 1903 TASKHANDLING_FILEIOERROR_FOR_WRITE, 1904 err ); 1905 bSuccess = sal_False; 1906 break; 1907 } 1908 else if( nWrittenBytes != sal_uInt64( nReadBytes ) ) 1909 { 1910 installError( CommandId, 1911 TASKHANDLING_FILEIOERROR_FOR_NO_SPACE ); 1912 bSuccess = sal_False; 1913 break; 1914 } 1915 } 1916 } while( nReadBytes == nRequestedBytes ); 1917 1918 err = aFile.close(); 1919 if( err != osl::FileBase::E_None ) 1920 { 1921 installError( CommandId, 1922 TASKHANDLING_FILEIOERROR_FOR_WRITE, 1923 err ); 1924 bSuccess = sal_False; 1925 } 1926 1927 return bSuccess; 1928 } 1929 1930 1931 1932 /*********************************************************************************/ 1933 /* */ 1934 /* insertDefaultProperties-Implementation */ 1935 /* */ 1936 /*********************************************************************************/ 1937 1938 1939 void SAL_CALL shell::insertDefaultProperties( const rtl::OUString& aUnqPath ) 1940 { 1941 osl::MutexGuard aGuard( m_aMutex ); 1942 1943 ContentMap::iterator it = 1944 m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first; 1945 1946 load( it,false ); 1947 1948 MyProperty ContentTProperty( ContentType ); 1949 1950 PropertySet& properties = *(it->second.properties); 1951 sal_Bool ContentNotDefau = properties.find( ContentTProperty ) != properties.end(); 1952 1953 shell::PropertySet::iterator it1 = m_aDefaultProperties.begin(); 1954 while( it1 != m_aDefaultProperties.end() ) 1955 { 1956 if( ContentNotDefau && it1->getPropertyName() == ContentType ) 1957 { 1958 // No insertion 1959 } 1960 else 1961 properties.insert( *it1 ); 1962 ++it1; 1963 } 1964 } 1965 1966 1967 1968 1969 /******************************************************************************/ 1970 /* */ 1971 /* mapping of file urls */ 1972 /* to uncpath and vice versa */ 1973 /* */ 1974 /******************************************************************************/ 1975 1976 1977 sal_Bool SAL_CALL shell::getUnqFromUrl( const rtl::OUString& Url,rtl::OUString& Unq ) 1978 { 1979 if( 0 == Url.compareToAscii( "file:///" ) || 1980 0 == Url.compareToAscii( "file://localhost/" ) || 1981 0 == Url.compareToAscii( "file://127.0.0.1/" ) ) 1982 { 1983 Unq = rtl::OUString::createFromAscii( "file:///" ); 1984 return false; 1985 } 1986 1987 sal_Bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Url,Unq ); 1988 1989 Unq = Url; 1990 1991 sal_Int32 l = Unq.getLength()-1; 1992 if( ! err && Unq.getStr()[ l ] == '/' && 1993 Unq.indexOf( '/', RTL_CONSTASCII_LENGTH("//") ) < l ) 1994 Unq = Unq.copy(0, Unq.getLength() - 1); 1995 1996 return err; 1997 } 1998 1999 2000 2001 sal_Bool SAL_CALL shell::getUrlFromUnq( const rtl::OUString& Unq,rtl::OUString& Url ) 2002 { 2003 sal_Bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Unq,Url ); 2004 2005 Url = Unq; 2006 2007 return err; 2008 } 2009 2010 2011 2012 // Helper function for public copy 2013 2014 osl::FileBase::RC SAL_CALL 2015 shell::copy_recursive( const rtl::OUString& srcUnqPath, 2016 const rtl::OUString& dstUnqPath, 2017 sal_Int32 TypeToCopy, 2018 sal_Bool testExistBeforeCopy ) 2019 throw() 2020 { 2021 osl::FileBase::RC err = osl::FileBase::E_None; 2022 2023 if( TypeToCopy == -1 ) // Document 2024 { 2025 err = osl_File_copy( srcUnqPath,dstUnqPath,testExistBeforeCopy ); 2026 } 2027 else if( TypeToCopy == +1 ) // Folder 2028 { 2029 osl::Directory aDir( srcUnqPath ); 2030 aDir.open(); 2031 2032 err = osl::Directory::create( dstUnqPath ); 2033 osl::FileBase::RC next = err; 2034 if( err == osl::FileBase::E_None ) 2035 { 2036 sal_Int32 n_Mask = FileStatusMask_FileURL | FileStatusMask_FileName | FileStatusMask_Type; 2037 2038 osl::DirectoryItem aDirItem; 2039 2040 while( err == osl::FileBase::E_None && ( next = aDir.getNextItem( aDirItem ) ) == osl::FileBase::E_None ) 2041 { 2042 sal_Bool IsDoc = false; 2043 osl::FileStatus aFileStatus( n_Mask ); 2044 aDirItem.getFileStatus( aFileStatus ); 2045 if( aFileStatus.isValid( FileStatusMask_Type ) ) 2046 IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular; 2047 2048 // Getting the information for the next recursive copy 2049 sal_Int32 newTypeToCopy = IsDoc ? -1 : +1; 2050 2051 rtl::OUString newSrcUnqPath; 2052 if( aFileStatus.isValid( FileStatusMask_FileURL ) ) 2053 newSrcUnqPath = aFileStatus.getFileURL(); 2054 2055 rtl::OUString newDstUnqPath = dstUnqPath; 2056 rtl::OUString tit; 2057 if( aFileStatus.isValid( FileStatusMask_FileName ) ) 2058 tit = rtl::Uri::encode( aFileStatus.getFileName(), 2059 rtl_UriCharClassPchar, 2060 rtl_UriEncodeIgnoreEscapes, 2061 RTL_TEXTENCODING_UTF8 ); 2062 2063 if( newDstUnqPath.lastIndexOf( sal_Unicode('/') ) != newDstUnqPath.getLength()-1 ) 2064 newDstUnqPath += rtl::OUString::createFromAscii( "/" ); 2065 2066 newDstUnqPath += tit; 2067 2068 if ( newSrcUnqPath != dstUnqPath ) 2069 err = copy_recursive( newSrcUnqPath,newDstUnqPath,newTypeToCopy,false ); 2070 } 2071 2072 if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT ) 2073 err = next; 2074 } 2075 aDir.close(); 2076 } 2077 2078 return err; 2079 } 2080 2081 2082 2083 // Helper function for mkfil,mkdir and write 2084 // Creates whole path 2085 // returns success of the operation 2086 2087 2088 sal_Bool SAL_CALL shell::ensuredir( sal_Int32 CommandId, 2089 const rtl::OUString& rUnqPath, 2090 sal_Int32 errorCode ) 2091 throw() 2092 { 2093 rtl::OUString aPath; 2094 2095 if ( rUnqPath.getLength() < 1 ) 2096 return sal_False; 2097 2098 if ( rUnqPath[ rUnqPath.getLength() - 1 ] == sal_Unicode( '/' ) ) 2099 aPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 ); 2100 else 2101 aPath = rUnqPath; 2102 2103 2104 // HACK: create directory on a mount point with nobrowse option 2105 // returns ENOSYS in any case !! 2106 osl::Directory aDirectory( aPath ); 2107 osl::FileBase::RC nError = aDirectory.open(); 2108 aDirectory.close(); 2109 2110 if( nError == osl::File::E_None ) 2111 return sal_True; 2112 2113 nError = osl::Directory::create( aPath ); 2114 2115 if( nError == osl::File::E_None ) 2116 notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath ); 2117 2118 sal_Bool bSuccess = ( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST ); 2119 2120 if( ! bSuccess ) 2121 { 2122 rtl::OUString aParentDir = getParentName( aPath ); 2123 2124 if ( aParentDir != aPath ) 2125 { // Create first the parent directory 2126 bSuccess = ensuredir( CommandId, 2127 getParentName( aPath ), 2128 errorCode ); 2129 2130 // After parent directory structure exists try it one's more 2131 2132 if ( bSuccess ) 2133 { // Parent directory exists, retry creation of directory 2134 nError = osl::Directory::create( aPath ); 2135 2136 if( nError == osl::File::E_None ) 2137 notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath ); 2138 2139 bSuccess =( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST ); 2140 } 2141 } 2142 } 2143 2144 if( ! bSuccess ) 2145 installError( CommandId, 2146 errorCode, 2147 nError ); 2148 2149 return bSuccess; 2150 } 2151 2152 2153 2154 2155 // 2156 // Given a sequence of properties seq, this method determines the mask 2157 // used to instantiate a osl::FileStatus, so that a call to 2158 // osl::DirectoryItem::getFileStatus fills the required fields. 2159 // 2160 2161 2162 void SAL_CALL 2163 shell::getMaskFromProperties( 2164 sal_Int32& n_Mask, 2165 const uno::Sequence< beans::Property >& seq ) 2166 { 2167 n_Mask = 0; 2168 for(sal_Int32 j = 0; j < seq.getLength(); ++j) { 2169 if(seq[j].Name == Title) 2170 n_Mask |= FileStatusMask_FileName; 2171 else if(seq[j].Name == CasePreservingURL) 2172 n_Mask |= FileStatusMask_FileURL; 2173 else if(seq[j].Name == IsDocument || 2174 seq[j].Name == IsFolder || 2175 seq[j].Name == IsVolume || 2176 seq[j].Name == IsRemoveable || 2177 seq[j].Name == IsRemote || 2178 seq[j].Name == IsCompactDisc || 2179 seq[j].Name == IsFloppy || 2180 seq[j].Name == ContentType) 2181 n_Mask |= (FileStatusMask_Type | FileStatusMask_LinkTargetURL); 2182 else if(seq[j].Name == Size) 2183 n_Mask |= (FileStatusMask_FileSize | 2184 FileStatusMask_Type | 2185 FileStatusMask_LinkTargetURL); 2186 else if(seq[j].Name == IsHidden || 2187 seq[j].Name == IsReadOnly) 2188 n_Mask |= FileStatusMask_Attributes; 2189 else if(seq[j].Name == DateModified) 2190 n_Mask |= FileStatusMask_ModifyTime; 2191 // n_Mask = FileStatusMask_FileURL; 2192 // n_Mask |= FileStatusMask_LinkTargetURL; 2193 // n_Mask |= FileStatusMask_FileName; 2194 // n_Mask |= FileStatusMask_Type; 2195 // n_Mask |= FileStatusMask_ModifyTime; 2196 // n_Mask |= FileStatusMask_FileSize; 2197 // n_Mask |= FileStatusMask_Attributes; 2198 } 2199 } 2200 2201 2202 2203 /*********************************************************************************/ 2204 /* */ 2205 /* load-Implementation */ 2206 /* */ 2207 /*********************************************************************************/ 2208 // 2209 // Load the properties from configuration, if create == true create them. 2210 // The Properties are stored under the url belonging to it->first. 2211 // 2212 2213 void SAL_CALL 2214 shell::load( const ContentMap::iterator& it, sal_Bool create ) 2215 { 2216 if( ! it->second.properties ) 2217 it->second.properties = new PropertySet; 2218 2219 if( ( ! it->second.xS.is() || 2220 ! it->second.xC.is() || 2221 ! it->second.xA.is() ) 2222 && m_xFileRegistry.is() ) 2223 { 2224 2225 uno::Reference< ucb::XPersistentPropertySet > xS = m_xFileRegistry->openPropertySet( it->first,create ); 2226 if( xS.is() ) 2227 { 2228 uno::Reference< beans::XPropertyContainer > xC( xS,uno::UNO_QUERY ); 2229 uno::Reference< beans::XPropertyAccess > xA( xS,uno::UNO_QUERY ); 2230 2231 it->second.xS = xS; 2232 it->second.xC = xC; 2233 it->second.xA = xA; 2234 2235 // Now put in all values in the storage in the local hash; 2236 2237 PropertySet& properties = *(it->second.properties); 2238 uno::Sequence< beans::Property > seq = xS->getPropertySetInfo()->getProperties(); 2239 2240 for( sal_Int32 i = 0; i < seq.getLength(); ++i ) 2241 { 2242 MyProperty readProp( false, 2243 seq[i].Name, 2244 seq[i].Handle, 2245 seq[i].Type, 2246 xS->getPropertyValue( seq[i].Name ), 2247 beans::PropertyState_DIRECT_VALUE, 2248 seq[i].Attributes ); 2249 if( properties.find( readProp ) == properties.end() ) 2250 properties.insert( readProp ); 2251 } 2252 } 2253 else if( create ) 2254 { 2255 // Catastrophic error 2256 } 2257 } 2258 } 2259 2260 2261 2262 2263 /*********************************************************************************/ 2264 /* */ 2265 /* commit-Implementation */ 2266 /* */ 2267 /*********************************************************************************/ 2268 // Commit inserts the determined properties in the filestatus object into 2269 // the internal map, so that is possible to determine on a subsequent 2270 // setting of file properties which properties have changed without filestat 2271 2272 2273 void SAL_CALL 2274 shell::commit( const shell::ContentMap::iterator& it, 2275 const osl::FileStatus& aFileStatus ) 2276 { 2277 uno::Any aAny; 2278 uno::Any emptyAny; 2279 shell::PropertySet::iterator it1; 2280 2281 if( it->second.properties == 0 ) 2282 { 2283 rtl::OUString aPath = it->first; 2284 insertDefaultProperties( aPath ); 2285 } 2286 2287 PropertySet& properties = *( it->second.properties ); 2288 2289 it1 = properties.find( MyProperty( Title ) ); 2290 if( it1 != properties.end() ) 2291 { 2292 if( aFileStatus.isValid( FileStatusMask_FileName ) ) 2293 { 2294 aAny <<= aFileStatus.getFileName(); 2295 it1->setValue( aAny ); 2296 } 2297 } 2298 2299 it1 = properties.find( MyProperty( CasePreservingURL ) ); 2300 if( it1 != properties.end() ) 2301 { 2302 if( aFileStatus.isValid( FileStatusMask_FileURL ) ) 2303 { 2304 aAny <<= aFileStatus.getFileURL(); 2305 it1->setValue( aAny ); 2306 } 2307 } 2308 2309 2310 sal_Bool isDirectory,isFile,isVolume,isRemoveable,isRemote,isFloppy,isCompactDisc; 2311 2312 sal_Int64 dirSize = 0; 2313 2314 if( aFileStatus.isValid( FileStatusMask_FileSize ) ) 2315 dirSize = aFileStatus.getFileSize(); 2316 2317 if( aFileStatus.isValid( FileStatusMask_Type ) ) 2318 { 2319 if( osl::FileStatus::Link == aFileStatus.getFileType() && 2320 aFileStatus.isValid( FileStatusMask_LinkTargetURL ) ) 2321 { 2322 osl::DirectoryItem aDirItem; 2323 osl::FileStatus aFileStatus2( FileStatusMask_Type ); 2324 if( osl::FileBase::E_None == osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(),aDirItem ) && 2325 osl::FileBase::E_None == aDirItem.getFileStatus( aFileStatus2 ) && 2326 aFileStatus2.isValid( FileStatusMask_Type ) ) 2327 { 2328 isVolume = osl::FileStatus::Volume == aFileStatus2.getFileType(); 2329 isDirectory = 2330 osl::FileStatus::Volume == aFileStatus2.getFileType() || 2331 osl::FileStatus::Directory == aFileStatus2.getFileType(); 2332 isFile = 2333 osl::FileStatus::Regular == aFileStatus2.getFileType(); 2334 2335 if( aFileStatus2.isValid( FileStatusMask_FileSize ) ) 2336 dirSize = aFileStatus2.getFileSize(); 2337 } 2338 else 2339 { 2340 // extremly ugly, but otherwise default construction 2341 // of aDirItem and aFileStatus2 2342 // before the preciding if 2343 isVolume = osl::FileStatus::Volume == aFileStatus.getFileType(); 2344 isDirectory = 2345 osl::FileStatus::Volume == aFileStatus.getFileType() || 2346 osl::FileStatus::Directory == aFileStatus.getFileType(); 2347 isFile = 2348 osl::FileStatus::Regular == aFileStatus.getFileType(); 2349 } 2350 } 2351 else 2352 { 2353 isVolume = osl::FileStatus::Volume == aFileStatus.getFileType(); 2354 isDirectory = 2355 osl::FileStatus::Volume == aFileStatus.getFileType() || 2356 osl::FileStatus::Directory == aFileStatus.getFileType(); 2357 isFile = 2358 osl::FileStatus::Regular == aFileStatus.getFileType(); 2359 } 2360 2361 it1 = properties.find( MyProperty( IsVolume ) ); 2362 if( it1 != properties.end() ) 2363 it1->setValue( uno::makeAny( isVolume ) ); 2364 2365 it1 = properties.find( MyProperty( IsFolder ) ); 2366 if( it1 != properties.end() ) 2367 it1->setValue( uno::makeAny( isDirectory ) ); 2368 2369 it1 = properties.find( MyProperty( IsDocument ) ); 2370 if( it1 != properties.end() ) 2371 it1->setValue( uno::makeAny( isFile ) ); 2372 2373 osl::VolumeInfo aVolumeInfo( VolumeInfoMask_Attributes ); 2374 if( isVolume && 2375 osl::FileBase::E_None == osl::Directory::getVolumeInfo( it->first,aVolumeInfo ) && 2376 aVolumeInfo.isValid( VolumeInfoMask_Attributes ) ) 2377 { 2378 // Retrieve the flags; 2379 isRemote = aVolumeInfo.getRemoteFlag(); 2380 isRemoveable = aVolumeInfo.getRemoveableFlag(); 2381 isCompactDisc = aVolumeInfo.getCompactDiscFlag(); 2382 isFloppy = aVolumeInfo.getFloppyDiskFlag(); 2383 2384 it1 = properties.find( MyProperty( IsRemote ) ); 2385 if( it1 != properties.end() ) 2386 it1->setValue( uno::makeAny( isRemote ) ); 2387 2388 it1 = properties.find( MyProperty( IsRemoveable ) ); 2389 if( it1 != properties.end() ) 2390 it1->setValue( uno::makeAny( isRemoveable ) ); 2391 2392 it1 = properties.find( MyProperty( IsCompactDisc ) ); 2393 if( it1 != properties.end() ) 2394 it1->setValue( uno::makeAny( isCompactDisc ) ); 2395 2396 it1 = properties.find( MyProperty( IsFloppy ) ); 2397 if( it1 != properties.end() ) 2398 it1->setValue( uno::makeAny( isFloppy ) ); 2399 } 2400 else 2401 { 2402 sal_Bool dummy = false; 2403 aAny <<= dummy; 2404 it1 = properties.find( MyProperty( IsRemote ) ); 2405 if( it1 != properties.end() ) 2406 it1->setValue( aAny ); 2407 2408 it1 = properties.find( MyProperty( IsRemoveable ) ); 2409 if( it1 != properties.end() ) 2410 it1->setValue( aAny ); 2411 2412 it1 = properties.find( MyProperty( IsCompactDisc ) ); 2413 if( it1 != properties.end() ) 2414 it1->setValue( aAny ); 2415 2416 it1 = properties.find( MyProperty( IsFloppy ) ); 2417 if( it1 != properties.end() ) 2418 it1->setValue( aAny ); 2419 } 2420 } 2421 else 2422 { 2423 isDirectory = sal_False; 2424 } 2425 2426 it1 = properties.find( MyProperty( Size ) ); 2427 if( it1 != properties.end() ) 2428 it1->setValue( uno::makeAny( dirSize ) ); 2429 2430 it1 = properties.find( MyProperty( IsReadOnly ) ); 2431 if( it1 != properties.end() ) 2432 { 2433 if( aFileStatus.isValid( FileStatusMask_Attributes ) ) 2434 { 2435 sal_uInt64 Attr = aFileStatus.getAttributes(); 2436 sal_Bool readonly = ( Attr & Attribute_ReadOnly ) != 0; 2437 it1->setValue( uno::makeAny( readonly ) ); 2438 } 2439 } 2440 2441 it1 = properties.find( MyProperty( IsHidden ) ); 2442 if( it1 != properties.end() ) 2443 { 2444 if( aFileStatus.isValid( FileStatusMask_Attributes ) ) 2445 { 2446 sal_uInt64 Attr = aFileStatus.getAttributes(); 2447 sal_Bool ishidden = ( Attr & Attribute_Hidden ) != 0; 2448 it1->setValue( uno::makeAny( ishidden ) ); 2449 } 2450 } 2451 2452 it1 = properties.find( MyProperty( DateModified ) ); 2453 if( it1 != properties.end() ) 2454 { 2455 if( aFileStatus.isValid( FileStatusMask_ModifyTime ) ) 2456 { 2457 TimeValue temp = aFileStatus.getModifyTime(); 2458 2459 // Convert system time to local time (for EA) 2460 TimeValue myLocalTime; 2461 osl_getLocalTimeFromSystemTime( &temp, &myLocalTime ); 2462 2463 oslDateTime myDateTime; 2464 osl_getDateTimeFromTimeValue( &myLocalTime, &myDateTime ); 2465 util::DateTime aDateTime; 2466 2467 aDateTime.HundredthSeconds = (unsigned short)(myDateTime.NanoSeconds / 10000000); 2468 aDateTime.Seconds = myDateTime.Seconds; 2469 aDateTime.Minutes = myDateTime.Minutes; 2470 aDateTime.Hours = myDateTime.Hours; 2471 aDateTime.Day = myDateTime.Day; 2472 aDateTime.Month = myDateTime.Month; 2473 aDateTime.Year = myDateTime.Year; 2474 it1->setValue( uno::makeAny( aDateTime ) ); 2475 } 2476 } 2477 2478 it1 = properties.find( MyProperty( CreatableContentsInfo ) ); 2479 if( it1 != properties.end() ) 2480 it1->setValue( uno::makeAny( 2481 isDirectory || !aFileStatus.isValid( FileStatusMask_Type ) 2482 ? queryCreatableContentsInfo() 2483 : uno::Sequence< ucb::ContentInfo >() ) ); 2484 } 2485 2486 2487 // Special optimized method for getting the properties of a 2488 // directoryitem, which is returned by osl::DirectoryItem::getNextItem() 2489 2490 2491 uno::Reference< sdbc::XRow > SAL_CALL 2492 shell::getv( 2493 Notifier* pNotifier, 2494 const uno::Sequence< beans::Property >& properties, 2495 osl::DirectoryItem& aDirItem, 2496 rtl::OUString& aUnqPath, 2497 sal_Bool& aIsRegular ) 2498 { 2499 uno::Sequence< uno::Any > seq( properties.getLength() ); 2500 2501 sal_Int32 n_Mask; 2502 getMaskFromProperties( n_Mask,properties ); 2503 2504 // Always retrieve the type and the target URL because item might be a link 2505 osl::FileStatus aFileStatus( n_Mask | 2506 FileStatusMask_FileURL | 2507 FileStatusMask_Type | 2508 FileStatusMask_LinkTargetURL ); 2509 aDirItem.getFileStatus( aFileStatus ); 2510 aUnqPath = aFileStatus.getFileURL(); 2511 2512 // If the directory item type is a link retrieve the type of the target 2513 2514 if ( aFileStatus.getFileType() == osl::FileStatus::Link ) 2515 { 2516 // Assume failure 2517 aIsRegular = false; 2518 osl::FileBase::RC result = osl::FileBase::E_INVAL; 2519 osl::DirectoryItem aTargetItem; 2520 osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(), aTargetItem ); 2521 if ( aTargetItem.is() ) 2522 { 2523 osl::FileStatus aTargetStatus( FileStatusMask_Type ); 2524 2525 if ( osl::FileBase::E_None == 2526 ( result = aTargetItem.getFileStatus( aTargetStatus ) ) ) 2527 aIsRegular = 2528 aTargetStatus.getFileType() == osl::FileStatus::Regular; 2529 } 2530 } 2531 else 2532 aIsRegular = aFileStatus.getFileType() == osl::FileStatus::Regular; 2533 2534 registerNotifier( aUnqPath,pNotifier ); 2535 insertDefaultProperties( aUnqPath ); 2536 { 2537 osl::MutexGuard aGuard( m_aMutex ); 2538 2539 shell::ContentMap::iterator it = m_aContent.find( aUnqPath ); 2540 commit( it,aFileStatus ); 2541 2542 shell::PropertySet::iterator it1; 2543 PropertySet& propset = *(it->second.properties); 2544 2545 for( sal_Int32 i = 0; i < seq.getLength(); ++i ) 2546 { 2547 MyProperty readProp( properties[i].Name ); 2548 it1 = propset.find( readProp ); 2549 if( it1 == propset.end() ) 2550 seq[i] = uno::Any(); 2551 else 2552 seq[i] = it1->getValue(); 2553 } 2554 } 2555 deregisterNotifier( aUnqPath,pNotifier ); 2556 2557 XRow_impl* p = new XRow_impl( this,seq ); 2558 return uno::Reference< sdbc::XRow >( p ); 2559 } 2560 2561 2562 2563 2564 2565 2566 // EventListener 2567 2568 2569 std::list< ContentEventNotifier* >* SAL_CALL 2570 shell::getContentEventListeners( const rtl::OUString& aName ) 2571 { 2572 std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >; 2573 std::list< ContentEventNotifier* >& listeners = *p; 2574 { 2575 osl::MutexGuard aGuard( m_aMutex ); 2576 shell::ContentMap::iterator it = m_aContent.find( aName ); 2577 if( it != m_aContent.end() && it->second.notifier ) 2578 { 2579 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier ); 2580 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin(); 2581 while( it1 != listOfNotifiers.end() ) 2582 { 2583 Notifier* pointer = *it1; 2584 ContentEventNotifier* notifier = pointer->cCEL(); 2585 if( notifier ) 2586 listeners.push_back( notifier ); 2587 ++it1; 2588 } 2589 } 2590 } 2591 return p; 2592 } 2593 2594 2595 2596 std::list< ContentEventNotifier* >* SAL_CALL 2597 shell::getContentDeletedEventListeners( const rtl::OUString& aName ) 2598 { 2599 std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >; 2600 std::list< ContentEventNotifier* >& listeners = *p; 2601 { 2602 osl::MutexGuard aGuard( m_aMutex ); 2603 shell::ContentMap::iterator it = m_aContent.find( aName ); 2604 if( it != m_aContent.end() && it->second.notifier ) 2605 { 2606 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier ); 2607 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin(); 2608 while( it1 != listOfNotifiers.end() ) 2609 { 2610 Notifier* pointer = *it1; 2611 ContentEventNotifier* notifier = pointer->cDEL(); 2612 if( notifier ) 2613 listeners.push_back( notifier ); 2614 ++it1; 2615 } 2616 } 2617 } 2618 return p; 2619 } 2620 2621 2622 void SAL_CALL 2623 shell::notifyInsert( std::list< ContentEventNotifier* >* listeners,const rtl::OUString& aChildName ) 2624 { 2625 std::list< ContentEventNotifier* >::iterator it = listeners->begin(); 2626 while( it != listeners->end() ) 2627 { 2628 (*it)->notifyChildInserted( aChildName ); 2629 delete (*it); 2630 ++it; 2631 } 2632 delete listeners; 2633 } 2634 2635 2636 void SAL_CALL 2637 shell::notifyContentDeleted( std::list< ContentEventNotifier* >* listeners ) 2638 { 2639 std::list< ContentEventNotifier* >::iterator it = listeners->begin(); 2640 while( it != listeners->end() ) 2641 { 2642 (*it)->notifyDeleted(); 2643 delete (*it); 2644 ++it; 2645 } 2646 delete listeners; 2647 } 2648 2649 2650 void SAL_CALL 2651 shell::notifyContentRemoved( std::list< ContentEventNotifier* >* listeners, 2652 const rtl::OUString& aChildName ) 2653 { 2654 std::list< ContentEventNotifier* >::iterator it = listeners->begin(); 2655 while( it != listeners->end() ) 2656 { 2657 (*it)->notifyRemoved( aChildName ); 2658 delete (*it); 2659 ++it; 2660 } 2661 delete listeners; 2662 } 2663 2664 2665 2666 2667 std::list< PropertySetInfoChangeNotifier* >* SAL_CALL 2668 shell::getPropertySetListeners( const rtl::OUString& aName ) 2669 { 2670 std::list< PropertySetInfoChangeNotifier* >* p = new std::list< PropertySetInfoChangeNotifier* >; 2671 std::list< PropertySetInfoChangeNotifier* >& listeners = *p; 2672 { 2673 osl::MutexGuard aGuard( m_aMutex ); 2674 shell::ContentMap::iterator it = m_aContent.find( aName ); 2675 if( it != m_aContent.end() && it->second.notifier ) 2676 { 2677 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier ); 2678 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin(); 2679 while( it1 != listOfNotifiers.end() ) 2680 { 2681 Notifier* pointer = *it1; 2682 PropertySetInfoChangeNotifier* notifier = pointer->cPSL(); 2683 if( notifier ) 2684 listeners.push_back( notifier ); 2685 ++it1; 2686 } 2687 } 2688 } 2689 return p; 2690 } 2691 2692 2693 void SAL_CALL 2694 shell::notifyPropertyAdded( std::list< PropertySetInfoChangeNotifier* >* listeners, 2695 const rtl::OUString& aPropertyName ) 2696 { 2697 std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin(); 2698 while( it != listeners->end() ) 2699 { 2700 (*it)->notifyPropertyAdded( aPropertyName ); 2701 delete (*it); 2702 ++it; 2703 } 2704 delete listeners; 2705 } 2706 2707 2708 void SAL_CALL 2709 shell::notifyPropertyRemoved( std::list< PropertySetInfoChangeNotifier* >* listeners, 2710 const rtl::OUString& aPropertyName ) 2711 { 2712 std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin(); 2713 while( it != listeners->end() ) 2714 { 2715 (*it)->notifyPropertyRemoved( aPropertyName ); 2716 delete (*it); 2717 ++it; 2718 } 2719 delete listeners; 2720 } 2721 2722 2723 2724 std::vector< std::list< ContentEventNotifier* >* >* SAL_CALL 2725 shell::getContentExchangedEventListeners( const rtl::OUString aOldPrefix, 2726 const rtl::OUString aNewPrefix, 2727 sal_Bool withChilds ) 2728 { 2729 2730 std::vector< std::list< ContentEventNotifier* >* >* aVectorOnHeap = 2731 new std::vector< std::list< ContentEventNotifier* >* >; 2732 std::vector< std::list< ContentEventNotifier* >* >& aVector = *aVectorOnHeap; 2733 2734 sal_Int32 count; 2735 rtl::OUString aOldName; 2736 rtl::OUString aNewName; 2737 std::vector< rtl::OUString > oldChildList; 2738 2739 { 2740 osl::MutexGuard aGuard( m_aMutex ); 2741 2742 if( ! withChilds ) 2743 { 2744 aOldName = aOldPrefix; 2745 aNewName = aNewPrefix; 2746 count = 1; 2747 } 2748 else 2749 { 2750 ContentMap::iterator itnames = m_aContent.begin(); 2751 while( itnames != m_aContent.end() ) 2752 { 2753 if( isChild( aOldPrefix,itnames->first ) ) 2754 { 2755 oldChildList.push_back( itnames->first ); 2756 } 2757 ++itnames; 2758 } 2759 count = oldChildList.size(); 2760 } 2761 2762 2763 for( sal_Int32 j = 0; j < count; ++j ) 2764 { 2765 std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >; 2766 std::list< ContentEventNotifier* >& listeners = *p; 2767 2768 if( withChilds ) 2769 { 2770 aOldName = oldChildList[j]; 2771 aNewName = newName( aNewPrefix,aOldPrefix,aOldName ); 2772 } 2773 2774 shell::ContentMap::iterator itold = m_aContent.find( aOldName ); 2775 if( itold != m_aContent.end() ) 2776 { 2777 shell::ContentMap::iterator itnew = m_aContent.insert( 2778 ContentMap::value_type( aNewName,UnqPathData() ) ).first; 2779 2780 // copy Ownership also 2781 delete itnew->second.properties; 2782 itnew->second.properties = itold->second.properties; 2783 itold->second.properties = 0; 2784 2785 // copy existing list 2786 std::list< Notifier* >* copyList = itnew->second.notifier; 2787 itnew->second.notifier = itold->second.notifier; 2788 itold->second.notifier = 0; 2789 2790 m_aContent.erase( itold ); 2791 2792 if( itnew != m_aContent.end() && itnew->second.notifier ) 2793 { 2794 std::list<Notifier*>& listOfNotifiers = *( itnew->second.notifier ); 2795 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin(); 2796 while( it1 != listOfNotifiers.end() ) 2797 { 2798 Notifier* pointer = *it1; 2799 ContentEventNotifier* notifier = pointer->cEXC( aNewName ); 2800 if( notifier ) 2801 listeners.push_back( notifier ); 2802 ++it1; 2803 } 2804 } 2805 2806 // Merge with preexisting notifiers 2807 // However, these may be in status BaseContent::Deleted 2808 if( copyList != 0 ) 2809 { 2810 std::list< Notifier* >::iterator copyIt = copyList->begin(); 2811 while( copyIt != copyList->end() ) 2812 { 2813 itnew->second.notifier->push_back( *copyIt ); 2814 ++copyIt; 2815 } 2816 } 2817 delete copyList; 2818 } 2819 aVector.push_back( p ); 2820 } 2821 } 2822 2823 return aVectorOnHeap; 2824 } 2825 2826 2827 2828 void SAL_CALL 2829 shell::notifyContentExchanged( std::vector< std::list< ContentEventNotifier* >* >* listeners_vec ) 2830 { 2831 std::list< ContentEventNotifier* >* listeners; 2832 for( sal_uInt32 i = 0; i < listeners_vec->size(); ++i ) 2833 { 2834 listeners = (*listeners_vec)[i]; 2835 std::list< ContentEventNotifier* >::iterator it = listeners->begin(); 2836 while( it != listeners->end() ) 2837 { 2838 (*it)->notifyExchanged(); 2839 delete (*it); 2840 ++it; 2841 } 2842 delete listeners; 2843 } 2844 delete listeners_vec; 2845 } 2846 2847 2848 2849 std::list< PropertyChangeNotifier* >* SAL_CALL 2850 shell::getPropertyChangeNotifier( const rtl::OUString& aName ) 2851 { 2852 std::list< PropertyChangeNotifier* >* p = new std::list< PropertyChangeNotifier* >; 2853 std::list< PropertyChangeNotifier* >& listeners = *p; 2854 { 2855 osl::MutexGuard aGuard( m_aMutex ); 2856 shell::ContentMap::iterator it = m_aContent.find( aName ); 2857 if( it != m_aContent.end() && it->second.notifier ) 2858 { 2859 std::list<Notifier*>& listOfNotifiers = *( it->second.notifier ); 2860 std::list<Notifier*>::iterator it1 = listOfNotifiers.begin(); 2861 while( it1 != listOfNotifiers.end() ) 2862 { 2863 Notifier* pointer = *it1; 2864 PropertyChangeNotifier* notifier = pointer->cPCL(); 2865 if( notifier ) 2866 listeners.push_back( notifier ); 2867 ++it1; 2868 } 2869 } 2870 } 2871 return p; 2872 } 2873 2874 2875 void SAL_CALL shell::notifyPropertyChanges( std::list< PropertyChangeNotifier* >* listeners, 2876 const uno::Sequence< beans::PropertyChangeEvent >& seqChanged ) 2877 { 2878 std::list< PropertyChangeNotifier* >::iterator it = listeners->begin(); 2879 while( it != listeners->end() ) 2880 { 2881 (*it)->notifyPropertyChanged( seqChanged ); 2882 delete (*it); 2883 ++it; 2884 } 2885 delete listeners; 2886 } 2887 2888 2889 2890 2891 /********************************************************************************/ 2892 /* remove persistent propertyset */ 2893 /********************************************************************************/ 2894 2895 void SAL_CALL 2896 shell::erasePersistentSet( const rtl::OUString& aUnqPath, 2897 sal_Bool withChilds ) 2898 { 2899 if( ! m_xFileRegistry.is() ) 2900 { 2901 OSL_ASSERT( m_xFileRegistry.is() ); 2902 return; 2903 } 2904 2905 uno::Sequence< rtl::OUString > seqNames; 2906 2907 if( withChilds ) 2908 { 2909 uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY ); 2910 seqNames = xName->getElementNames(); 2911 } 2912 2913 sal_Int32 count = withChilds ? seqNames.getLength() : 1; 2914 2915 rtl::OUString 2916 old_Name = aUnqPath; 2917 2918 for( sal_Int32 j = 0; j < count; ++j ) 2919 { 2920 if( withChilds && ! ( isChild( old_Name,seqNames[j] ) ) ) 2921 continue; 2922 2923 if( withChilds ) 2924 { 2925 old_Name = seqNames[j]; 2926 } 2927 2928 { 2929 // Release possible references 2930 osl::MutexGuard aGuard( m_aMutex ); 2931 ContentMap::iterator it = m_aContent.find( old_Name ); 2932 if( it != m_aContent.end() ) 2933 { 2934 it->second.xS = 0; 2935 it->second.xC = 0; 2936 it->second.xA = 0; 2937 2938 delete it->second.properties; 2939 it->second.properties = 0; 2940 } 2941 } 2942 2943 if( m_xFileRegistry.is() ) 2944 m_xFileRegistry->removePropertySet( old_Name ); 2945 } 2946 } 2947 2948 2949 2950 2951 /********************************************************************************/ 2952 /* copy persistent propertyset */ 2953 /* from srcUnqPath to dstUnqPath */ 2954 /********************************************************************************/ 2955 2956 2957 void SAL_CALL 2958 shell::copyPersistentSet( const rtl::OUString& srcUnqPath, 2959 const rtl::OUString& dstUnqPath, 2960 sal_Bool withChilds ) 2961 { 2962 if( ! m_xFileRegistry.is() ) 2963 { 2964 OSL_ASSERT( m_xFileRegistry.is() ); 2965 return; 2966 } 2967 2968 uno::Sequence< rtl::OUString > seqNames; 2969 2970 if( withChilds ) 2971 { 2972 uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY ); 2973 seqNames = xName->getElementNames(); 2974 } 2975 2976 sal_Int32 count = withChilds ? seqNames.getLength() : 1; 2977 2978 rtl::OUString 2979 old_Name = srcUnqPath, 2980 new_Name = dstUnqPath; 2981 2982 for( sal_Int32 j = 0; j < count; ++j ) 2983 { 2984 if( withChilds && ! ( isChild( srcUnqPath,seqNames[j] ) ) ) 2985 continue; 2986 2987 if( withChilds ) 2988 { 2989 old_Name = seqNames[j]; 2990 new_Name = newName( dstUnqPath,srcUnqPath,old_Name ); 2991 } 2992 2993 uno::Reference< XPersistentPropertySet > x_src; 2994 2995 if( m_xFileRegistry.is() ) 2996 { 2997 x_src = m_xFileRegistry->openPropertySet( old_Name,false ); 2998 m_xFileRegistry->removePropertySet( new_Name ); 2999 } 3000 3001 if( x_src.is() ) 3002 { 3003 uno::Sequence< beans::Property > seqProperty = 3004 x_src->getPropertySetInfo()->getProperties(); 3005 3006 if( seqProperty.getLength() ) 3007 { 3008 uno::Reference< XPersistentPropertySet > 3009 x_dstS = m_xFileRegistry->openPropertySet( new_Name,true ); 3010 uno::Reference< beans::XPropertyContainer > 3011 x_dstC( x_dstS,uno::UNO_QUERY ); 3012 3013 for( sal_Int32 i = 0; i < seqProperty.getLength(); ++i ) 3014 { 3015 x_dstC->addProperty( seqProperty[i].Name, 3016 seqProperty[i].Attributes, 3017 x_src->getPropertyValue( seqProperty[i].Name ) ); 3018 } 3019 } 3020 } 3021 } // end for( sal_Int... 3022 } 3023 3024 uno::Sequence< ucb::ContentInfo > shell::queryCreatableContentsInfo() 3025 { 3026 uno::Sequence< ucb::ContentInfo > seq(2); 3027 3028 // file 3029 seq[0].Type = FileContentType; 3030 seq[0].Attributes = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM 3031 | ucb::ContentInfoAttribute::KIND_DOCUMENT; 3032 3033 uno::Sequence< beans::Property > props( 1 ); 3034 props[0] = beans::Property( 3035 rtl::OUString::createFromAscii( "Title" ), 3036 -1, 3037 getCppuType( static_cast< rtl::OUString* >( 0 ) ), 3038 beans::PropertyAttribute::MAYBEVOID 3039 | beans::PropertyAttribute::BOUND ); 3040 seq[0].Properties = props; 3041 3042 // folder 3043 seq[1].Type = FolderContentType; 3044 seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER; 3045 seq[1].Properties = props; 3046 return seq; 3047 } 3048 3049 /*******************************************************************************/ 3050 /* */ 3051 /* some misceancellous static functions */ 3052 /* */ 3053 /*******************************************************************************/ 3054 3055 void SAL_CALL 3056 shell::getScheme( rtl::OUString& Scheme ) 3057 { 3058 Scheme = rtl::OUString::createFromAscii( "file" ); 3059 } 3060 3061 rtl::OUString SAL_CALL 3062 shell::getImplementationName_static( void ) 3063 { 3064 return rtl::OUString::createFromAscii( "com.sun.star.comp.ucb.FileProvider" ); 3065 } 3066 3067 3068 uno::Sequence< rtl::OUString > SAL_CALL 3069 shell::getSupportedServiceNames_static( void ) 3070 { 3071 rtl::OUString Supported = rtl::OUString::createFromAscii( "com.sun.star.ucb.FileContentProvider" ) ; 3072 com::sun::star::uno::Sequence< rtl::OUString > Seq( &Supported,1 ); 3073 return Seq; 3074 } 3075