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