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