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 #include <osl/mutex.hxx> 25 #include <osl/diagnose.h> 26 27 #include "fileaccess/dllapi.h" 28 29 #include <uno/mapping.hxx> 30 31 #include <cppuhelper/factory.hxx> 32 #include <cppuhelper/implbase1.hxx> 33 #include <cppuhelper/implementationentry.hxx> 34 35 #include <tools/ref.hxx> 36 #include <tools/urlobj.hxx> 37 #include <ucbhelper/content.hxx> 38 #include <unotools/streamwrap.hxx> 39 #include <tools/stream.hxx> 40 41 #include <com/sun/star/beans/Property.hpp> 42 #include <com/sun/star/beans/XPropertySet.hpp> 43 #include <com/sun/star/container/XChild.hpp> 44 #include <com/sun/star/io/XActiveDataSink.hpp> 45 #include <com/sun/star/io/XActiveDataSource.hpp> 46 #include <com/sun/star/io/XActiveDataStreamer.hpp> 47 #include <com/sun/star/sdbc/XResultSet.hpp> 48 #include <com/sun/star/ucb/CommandFailedException.hpp> 49 #include <com/sun/star/ucb/ContentInfo.hpp> 50 #include <com/sun/star/ucb/ContentInfoAttribute.hpp> 51 #include <com/sun/star/ucb/InsertCommandArgument.hpp> 52 #include <com/sun/star/ucb/InteractiveIOException.hpp> 53 #include <com/sun/star/ucb/NameClash.hpp> 54 #include <com/sun/star/ucb/NameClashException.hpp> 55 #include <com/sun/star/ucb/OpenCommandArgument2.hpp> 56 #include <com/sun/star/ucb/OpenMode.hpp> 57 #include <com/sun/star/ucb/XCommandEnvironment.hpp> 58 #include <com/sun/star/ucb/XContent.hpp> 59 #include <com/sun/star/ucb/XContentAccess.hpp> 60 #include <com/sun/star/ucb/XSimpleFileAccess3.hpp> 61 #include <com/sun/star/util/XMacroExpander.hpp> 62 63 using namespace ::com::sun::star::uno; 64 using namespace ::com::sun::star::lang; 65 using namespace ::com::sun::star::io; 66 using namespace ::com::sun::star::ucb; 67 using namespace ::com::sun::star::sdbc; 68 using namespace ::com::sun::star::task; 69 using namespace ::com::sun::star::util; 70 using namespace ::com::sun::star::beans; 71 using namespace ::com::sun::star::registry; 72 using namespace ::com::sun::star::container; 73 74 namespace io_FileAccess 75 { 76 77 78 //=========================================================================== 79 // Implementation XSimpleFileAccess 80 81 typedef cppu::WeakImplHelper1< XSimpleFileAccess3 > FileAccessHelper; 82 class OCommandEnvironment; 83 84 class OFileAccess : public FileAccessHelper 85 { 86 Reference< XComponentContext > mxCtx; 87 Reference< XCommandEnvironment > mxEnvironment; 88 OCommandEnvironment* mpEnvironment; 89 90 void transferImpl( const rtl::OUString& rSource, const rtl::OUString& rDest, sal_Bool bMoveData ); 91 bool createNewFile( const rtl::OUString & rParentURL, 92 const rtl::OUString & rTitle, 93 const Reference< XInputStream >& data ); 94 95 public: 96 OFileAccess( const Reference< XComponentContext > & xCtx ) 97 : mxCtx( xCtx ), mpEnvironment( NULL ) {} 98 99 // Methods 100 virtual void SAL_CALL copy( const ::rtl::OUString& SourceURL, const ::rtl::OUString& DestURL ); 101 virtual void SAL_CALL move( const ::rtl::OUString& SourceURL, const ::rtl::OUString& DestURL ); 102 virtual void SAL_CALL kill( const ::rtl::OUString& FileURL ); 103 virtual sal_Bool SAL_CALL isFolder( const ::rtl::OUString& FileURL ); 104 virtual sal_Bool SAL_CALL isReadOnly( const ::rtl::OUString& FileURL ); 105 virtual void SAL_CALL setReadOnly( const ::rtl::OUString& FileURL, sal_Bool bReadOnly ); 106 virtual void SAL_CALL createFolder( const ::rtl::OUString& NewFolderURL ); 107 virtual sal_Int32 SAL_CALL getSize( const ::rtl::OUString& FileURL ); 108 virtual ::rtl::OUString SAL_CALL getContentType( const ::rtl::OUString& FileURL ); 109 virtual ::com::sun::star::util::DateTime SAL_CALL getDateTimeModified( const ::rtl::OUString& FileURL ); 110 virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFolderContents( const ::rtl::OUString& FolderURL, sal_Bool bIncludeFolders ); 111 virtual sal_Bool SAL_CALL exists( const ::rtl::OUString& FileURL ); 112 virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL openFileRead( const ::rtl::OUString& FileURL ); 113 virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > SAL_CALL openFileWrite( const ::rtl::OUString& FileURL ); 114 virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream > SAL_CALL openFileReadWrite( const ::rtl::OUString& FileURL ); 115 virtual void SAL_CALL setInteractionHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler ); 116 virtual void SAL_CALL writeFile( const ::rtl::OUString& FileURL, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& data ); 117 virtual sal_Bool SAL_CALL isHidden( const ::rtl::OUString& FileURL ); 118 virtual void SAL_CALL setHidden( const ::rtl::OUString& FileURL, sal_Bool bHidden ); 119 }; 120 121 122 //=========================================================================== 123 // Implementation XActiveDataSink 124 125 typedef cppu::WeakImplHelper1< XActiveDataSink > ActiveDataSinkHelper; 126 127 class OActiveDataSink : public ActiveDataSinkHelper 128 { 129 Reference< XInputStream > mxStream; 130 131 public: 132 133 // Methods 134 virtual void SAL_CALL setInputStream( const Reference< XInputStream >& aStream ); 135 virtual Reference< XInputStream > SAL_CALL getInputStream( ); 136 }; 137 138 void OActiveDataSink::setInputStream( const Reference< XInputStream >& aStream ) 139 { 140 mxStream = aStream; 141 } 142 143 Reference< XInputStream > OActiveDataSink::getInputStream() 144 { 145 return mxStream; 146 } 147 148 149 //=========================================================================== 150 // Implementation XActiveDataSource 151 152 typedef cppu::WeakImplHelper1< XActiveDataSource > ActiveDataSourceHelper; 153 154 class OActiveDataSource : public ActiveDataSourceHelper 155 { 156 Reference< XOutputStream > mxStream; 157 158 public: 159 160 // Methods 161 virtual void SAL_CALL setOutputStream( const Reference< XOutputStream >& aStream ); 162 virtual Reference< XOutputStream > SAL_CALL getOutputStream(); 163 }; 164 165 void OActiveDataSource::setOutputStream( const Reference< XOutputStream >& aStream ) 166 { 167 mxStream = aStream; 168 } 169 170 Reference< XOutputStream > OActiveDataSource::getOutputStream() 171 { 172 return mxStream; 173 } 174 175 176 //=========================================================================== 177 // Implementation XActiveDataStreamer 178 179 typedef cppu::WeakImplHelper1< XActiveDataStreamer > ActiveDataStreamerHelper; 180 181 class OActiveDataStreamer : public ActiveDataStreamerHelper 182 { 183 Reference< XStream > mxStream; 184 185 public: 186 187 // Methods 188 virtual void SAL_CALL setStream( const Reference< XStream >& aStream ); 189 virtual Reference< XStream > SAL_CALL getStream(); 190 }; 191 192 void OActiveDataStreamer::setStream( const Reference< XStream >& aStream ) 193 { 194 mxStream = aStream; 195 } 196 197 Reference< XStream > OActiveDataStreamer::getStream() 198 { 199 return mxStream; 200 } 201 202 203 204 //=========================================================================== 205 // Implementation XCommandEnvironment 206 207 typedef cppu::WeakImplHelper1< XCommandEnvironment > CommandEnvironmentHelper; 208 209 class OCommandEnvironment : public CommandEnvironmentHelper 210 { 211 Reference< XInteractionHandler > mxInteraction; 212 213 public: 214 void setHandler( Reference< XInteractionHandler > xInteraction_ ) 215 { 216 mxInteraction = xInteraction_; 217 } 218 219 // Methods 220 virtual Reference< XInteractionHandler > SAL_CALL getInteractionHandler(); 221 virtual Reference< XProgressHandler > SAL_CALL getProgressHandler(); 222 }; 223 224 Reference< XInteractionHandler > OCommandEnvironment::getInteractionHandler() 225 { 226 return mxInteraction; 227 } 228 229 Reference< XProgressHandler > OCommandEnvironment::getProgressHandler() 230 { 231 Reference< XProgressHandler > xRet; 232 return xRet; 233 } 234 235 //=========================================================================== 236 237 void OFileAccess::transferImpl( const rtl::OUString& rSource, 238 const rtl::OUString& rDest, 239 sal_Bool bMoveData ) 240 { 241 // SfxContentHelper::Transfer_Impl 242 INetURLObject aSourceObj( rSource, INET_PROT_FILE ); 243 INetURLObject aDestObj( rDest, INET_PROT_FILE ); 244 String aName = aDestObj.getName( 245 INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); 246 String aDestURL; 247 String aSourceURL = aSourceObj.GetMainURL( INetURLObject::NO_DECODE ); 248 if ( aDestObj.removeSegment() ) 249 { 250 // hierarchical URL. 251 252 aDestObj.setFinalSlash(); 253 aDestURL = aDestObj.GetMainURL( INetURLObject::NO_DECODE ); 254 } 255 else 256 { 257 // non-hierachical URL 258 259 // #i29648# 260 // 261 #if 0 262 // Note: A hierarchical UCB content implements interface XChild, which 263 // has a method getParent(). Unfortunately this does not always help 264 // here, because it is not guaranteed that a content object for a 265 // non-existing resource can be created. Thus, it will happen that an 266 // exception is thrown when trying to create a UCB content for the 267 // destination URL. 268 269 try 270 { 271 ucbhelper::Content aFullDest( 272 aDestObj.GetMainURL( 273 INetURLObject::NO_DECODE ), mxEnvironment ); 274 275 Reference< XChild > xChild( aFullDest.get(), UNO_QUERY_THROW ); 276 Reference< com::sun::star::ucb::XContent > 277 xParent( xChild->getParent(), UNO_QUERY_THROW ); 278 ucbhelper::Content aParent( xParent, mxEnvironment ); 279 280 aDestURL = aParent.getURL(); 281 282 rtl::OUString aNameTmp; 283 aFullDest.getPropertyValue( 284 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ) ) 285 >>= aNameTmp; 286 aName = aNameTmp; 287 } 288 catch ( Exception const & ) 289 { 290 throw RuntimeException( 291 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 292 "OFileAccess::transferrImpl - Unable to " 293 "obtain destination folder URL!" ) ), 294 static_cast< cppu::OWeakObject * >( this ) ); 295 } 296 #else 297 if ( aDestObj.GetProtocol() == INET_PROT_VND_SUN_STAR_EXPAND ) 298 { 299 // Hack: Expand destination URL using Macro Expander and try again 300 // with the hopefully hierarchical expanded URL... 301 302 try 303 { 304 Reference< XMacroExpander > xExpander; 305 306 mxCtx->getValueByName( 307 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 308 "/singletons/com.sun.star.util.theMacroExpander" ) ) ) 309 >>= xExpander; 310 311 OSL_ENSURE( xExpander.is(), 312 "Unable to obtain macro expander singleton!" ); 313 314 aDestURL = xExpander->expandMacros( 315 aDestObj.GetURLPath( INetURLObject::DECODE_WITH_CHARSET ) ); 316 } 317 catch ( Exception const & ) 318 { 319 throw RuntimeException( 320 rtl::OUString( 321 RTL_CONSTASCII_USTRINGPARAM( 322 "OFileAccess::transferrImpl - Unable to obtain " 323 "destination folder URL!" ) ), 324 static_cast< cppu::OWeakObject * >( this ) ); 325 } 326 327 transferImpl( rSource, aDestURL, bMoveData ); 328 return; 329 } 330 331 throw RuntimeException( 332 rtl::OUString( 333 RTL_CONSTASCII_USTRINGPARAM( 334 "OFileAccess::transferrImpl - Unable to obtain " 335 "destination folder URL!" ) ), 336 static_cast< cppu::OWeakObject * >( this ) ); 337 #endif 338 } 339 340 ucbhelper::Content aDestPath( aDestURL, mxEnvironment ); 341 ucbhelper::Content aSrc ( aSourceURL, mxEnvironment ); 342 343 try 344 { 345 aDestPath.transferContent( aSrc, 346 bMoveData 347 ? ucbhelper::InsertOperation_MOVE 348 : ucbhelper::InsertOperation_COPY, 349 aName, 350 ::com::sun::star::ucb::NameClash::OVERWRITE ); 351 } 352 catch ( ::com::sun::star::ucb::CommandFailedException const & ) 353 { 354 // Interaction Handler already handled the error that has occurred... 355 } 356 } 357 358 void OFileAccess::copy( const rtl::OUString& SourceURL, const rtl::OUString& DestURL ) 359 { 360 transferImpl( SourceURL, DestURL, sal_False ); 361 } 362 363 void OFileAccess::move( const rtl::OUString& SourceURL, const rtl::OUString& DestURL ) 364 { 365 transferImpl( SourceURL, DestURL, sal_True ); 366 } 367 368 void OFileAccess::kill( const rtl::OUString& FileURL ) 369 { 370 // SfxContentHelper::Kill 371 INetURLObject aDeleteObj( FileURL, INET_PROT_FILE ); 372 ucbhelper::Content aCnt( aDeleteObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment ); 373 try 374 { 375 aCnt.executeCommand( rtl::OUString::createFromAscii( "delete" ), makeAny( sal_Bool( sal_True ) ) ); 376 } 377 catch ( ::com::sun::star::ucb::CommandFailedException const & ) 378 { 379 // Interaction Handler already handled the error that has occurred... 380 } 381 } 382 383 sal_Bool OFileAccess::isFolder( const rtl::OUString& FileURL ) 384 { 385 sal_Bool bRet = sal_False; 386 try 387 { 388 INetURLObject aURLObj( FileURL, INET_PROT_FILE ); 389 ucbhelper::Content aCnt( aURLObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment ); 390 bRet = aCnt.isFolder(); 391 } 392 catch (Exception &) {} 393 return bRet; 394 } 395 396 sal_Bool OFileAccess::isReadOnly( const rtl::OUString& FileURL ) 397 { 398 INetURLObject aURLObj( FileURL, INET_PROT_FILE ); 399 ucbhelper::Content aCnt( aURLObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment ); 400 Any aRetAny = aCnt.getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ) ); 401 sal_Bool bRet = sal_False; 402 aRetAny >>= bRet; 403 return bRet; 404 } 405 406 void OFileAccess::setReadOnly( const rtl::OUString& FileURL, sal_Bool bReadOnly ) 407 { 408 INetURLObject aURLObj( FileURL, INET_PROT_FILE ); 409 ucbhelper::Content aCnt( aURLObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment ); 410 Any aAny; 411 aAny <<= bReadOnly; 412 aCnt.setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ), aAny ); 413 } 414 415 void OFileAccess::createFolder( const rtl::OUString& NewFolderURL ) 416 { 417 // Does the folder already exist? 418 if( !NewFolderURL.getLength() || isFolder( NewFolderURL ) ) 419 return; 420 421 // SfxContentHelper::MakeFolder 422 INetURLObject aURL( NewFolderURL, INET_PROT_FILE ); 423 String aNewFolderURLStr = aURL.GetMainURL( INetURLObject::NO_DECODE ); 424 String aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); 425 if ( aTitle.Len() ) 426 { 427 aURL.removeSegment(); 428 429 // Does the base folder exist? Otherwise create it first 430 String aBaseFolderURLStr = aURL.GetMainURL( INetURLObject::NO_DECODE ); 431 if( !isFolder( aBaseFolderURLStr ) ) 432 { 433 createFolder( aBaseFolderURLStr ); 434 } 435 } 436 437 ucbhelper::Content aCnt( aURL.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment ); 438 439 Sequence< ContentInfo > aInfo = aCnt.queryCreatableContentsInfo(); 440 sal_Int32 nCount = aInfo.getLength(); 441 if ( nCount == 0 ) 442 return; 443 444 for ( sal_Int32 i = 0; i < nCount; ++i ) 445 { 446 // Simply look for the first KIND_FOLDER... 447 const ContentInfo & rCurr = aInfo[i]; 448 if ( rCurr.Attributes & ContentInfoAttribute::KIND_FOLDER ) 449 { 450 // Make sure the only required bootstrap property is "Title", 451 const Sequence< Property > & rProps = rCurr.Properties; 452 if ( rProps.getLength() != 1 ) 453 continue; 454 455 if ( !rProps[ 0 ].Name.equalsAsciiL( 456 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) 457 continue; 458 459 Sequence<rtl::OUString> aNames(1); 460 rtl::OUString* pNames = aNames.getArray(); 461 pNames[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ); 462 Sequence< Any > aValues(1); 463 Any* pValues = aValues.getArray(); 464 pValues[0] = makeAny( rtl::OUString( aTitle ) ); 465 466 ucbhelper::Content aNew; 467 try 468 { 469 if ( !aCnt.insertNewContent( rCurr.Type, aNames, aValues, aNew ) ) 470 continue; 471 472 // Success. We're done. 473 return; 474 } 475 catch ( ::com::sun::star::ucb::CommandFailedException const & ) 476 { 477 // Interaction Handler already handled the error that has occurred... 478 continue; 479 } 480 } 481 } 482 } 483 484 sal_Int32 OFileAccess::getSize( const rtl::OUString& FileURL ) 485 { 486 // SfxContentHelper::GetSize 487 sal_Int32 nSize = 0; 488 sal_Int64 nTemp = 0; 489 INetURLObject aObj( FileURL, INET_PROT_FILE ); 490 ucbhelper::Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment ); 491 aCnt.getPropertyValue( rtl::OUString::createFromAscii( "Size" ) ) >>= nTemp; 492 nSize = (sal_Int32)nTemp; 493 return nSize; 494 } 495 496 rtl::OUString OFileAccess::getContentType( const rtl::OUString& FileURL ) 497 { 498 INetURLObject aObj( FileURL, INET_PROT_FILE ); 499 ucbhelper::Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment ); 500 501 Reference< XContent > xContent = aCnt.get(); 502 rtl::OUString aTypeStr = xContent->getContentType(); 503 return aTypeStr; 504 } 505 506 DateTime OFileAccess::getDateTimeModified( const rtl::OUString& FileURL ) 507 { 508 INetURLObject aFileObj( FileURL, INET_PROT_FILE ); 509 DateTime aDateTime; 510 511 Reference< XCommandEnvironment > aCmdEnv; 512 ucbhelper::Content aYoung( aFileObj.GetMainURL( INetURLObject::NO_DECODE ), aCmdEnv ); 513 aYoung.getPropertyValue( rtl::OUString::createFromAscii( "DateModified" ) ) >>= aDateTime; 514 return aDateTime; 515 } 516 517 518 DECLARE_LIST( StringList_Impl, rtl::OUString* ) 519 520 Sequence< rtl::OUString > OFileAccess::getFolderContents( const rtl::OUString& FolderURL, sal_Bool bIncludeFolders ) 521 { 522 // SfxContentHelper::GetFolderContents 523 524 StringList_Impl* pFiles = NULL; 525 INetURLObject aFolderObj( FolderURL, INET_PROT_FILE ); 526 527 ucbhelper::Content aCnt( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment ); 528 Reference< XResultSet > xResultSet; 529 Sequence< rtl::OUString > aProps(0); 530 //Sequence< rtl::OUString > aProps(1); 531 //rtl::OUString* pProps = aProps.getArray(); 532 //pProps[0] == rtl::OUString::createFromAscii( "Url" ); 533 534 ucbhelper::ResultSetInclude eInclude = bIncludeFolders ? ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS : ucbhelper::INCLUDE_DOCUMENTS_ONLY; 535 536 try 537 { 538 xResultSet = aCnt.createCursor( aProps, eInclude ); 539 } 540 catch ( ::com::sun::star::ucb::CommandFailedException const & ) 541 { 542 // Interaction Handler already handled the error that has occurred... 543 } 544 545 if ( xResultSet.is() ) 546 { 547 pFiles = new StringList_Impl; 548 Reference< com::sun::star::ucb::XContentAccess > xContentAccess( xResultSet, UNO_QUERY ); 549 550 while ( xResultSet->next() ) 551 { 552 rtl::OUString aId = xContentAccess->queryContentIdentifierString(); 553 INetURLObject aURL( aId, INET_PROT_FILE ); 554 rtl::OUString* pFile = new rtl::OUString( aURL.GetMainURL( INetURLObject::NO_DECODE ) ); 555 pFiles->Insert( pFile, LIST_APPEND ); 556 } 557 } 558 559 if ( pFiles ) 560 { 561 sal_uIntPtr nCount = pFiles->Count(); 562 Sequence < rtl::OUString > aRet( nCount ); 563 rtl::OUString* pRet = aRet.getArray(); 564 for ( sal_uInt16 i = 0; i < nCount; ++i ) 565 { 566 rtl::OUString* pFile = pFiles->GetObject(i); 567 pRet[i] = *( pFile ); 568 delete pFile; 569 } 570 delete pFiles; 571 return aRet; 572 } 573 else 574 return Sequence < rtl::OUString > (); 575 } 576 577 sal_Bool OFileAccess::exists( const rtl::OUString& FileURL ) 578 { 579 sal_Bool bRet = sal_False; 580 try 581 { 582 bRet = isFolder( FileURL ); 583 if( !bRet ) 584 { 585 Reference< XInputStream > xStream = openFileRead( FileURL ); 586 bRet = xStream.is(); 587 if( bRet ) 588 xStream->closeInput(); 589 } 590 } 591 catch (Exception &) {} 592 return bRet; 593 } 594 595 Reference< XInputStream > OFileAccess::openFileRead( const rtl::OUString& FileURL ) 596 { 597 Reference< XInputStream > xRet; 598 INetURLObject aObj( FileURL, INET_PROT_FILE ); 599 ucbhelper::Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment ); 600 601 Reference< XActiveDataSink > xSink = (XActiveDataSink*)(new OActiveDataSink()); 602 603 try 604 { 605 sal_Bool bRet = aCnt.openStream( xSink ); 606 if( bRet ) 607 xRet = xSink->getInputStream(); 608 } 609 catch ( ::com::sun::star::ucb::CommandFailedException const & ) 610 { 611 // Interaction Handler already handled the error that has occurred... 612 } 613 614 return xRet; 615 } 616 617 Reference< XOutputStream > OFileAccess::openFileWrite( const rtl::OUString& FileURL ) 618 { 619 Reference< XOutputStream > xRet; 620 Reference< XStream > xStream = OFileAccess::openFileReadWrite( FileURL ); 621 if( xStream.is() ) 622 xRet = xStream->getOutputStream(); 623 return xRet; 624 } 625 626 Reference< XStream > OFileAccess::openFileReadWrite( const rtl::OUString& FileURL ) 627 { 628 Reference< XActiveDataStreamer > xSink = (XActiveDataStreamer*)new OActiveDataStreamer(); 629 Reference< XInterface > xSinkIface = Reference< XInterface >::query( xSink ); 630 631 OpenCommandArgument2 aArg; 632 aArg.Mode = OpenMode::DOCUMENT; 633 aArg.Priority = 0; // unused 634 aArg.Sink = xSink; 635 aArg.Properties = Sequence< Property >( 0 ); // unused 636 637 Any aCmdArg; 638 aCmdArg <<= aArg; 639 640 INetURLObject aFileObj( FileURL, INET_PROT_FILE ); 641 ucbhelper::Content aCnt( aFileObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment ); 642 643 // Be silent... 644 Reference< XInteractionHandler > xIH; 645 if ( mpEnvironment ) 646 { 647 xIH = mpEnvironment->getInteractionHandler(); 648 mpEnvironment->setHandler( 0 ); 649 } 650 651 try 652 { 653 aCnt.executeCommand( rtl::OUString::createFromAscii( "open" ), aCmdArg ); 654 } 655 catch ( InteractiveIOException const & e ) 656 { 657 if ( xIH.is() ) 658 mpEnvironment->setHandler( xIH ); 659 660 if ( e.Code == IOErrorCode_NOT_EXISTING ) 661 { 662 // Create file... 663 SvMemoryStream aStream(0,0); 664 ::utl::OInputStreamWrapper* pInput = new ::utl::OInputStreamWrapper( aStream ); 665 Reference< XInputStream > xInput( pInput ); 666 InsertCommandArgument aInsertArg; 667 aInsertArg.Data = xInput; 668 aInsertArg.ReplaceExisting = sal_False; 669 670 aCmdArg <<= aInsertArg; 671 aCnt.executeCommand( rtl::OUString::createFromAscii( "insert" ), aCmdArg ); 672 673 // Retry... 674 return openFileReadWrite( FileURL ); 675 } 676 677 throw; 678 } 679 680 if ( xIH.is() ) 681 mpEnvironment->setHandler( xIH ); 682 683 Reference< XStream > xRet = xSink->getStream(); 684 return xRet; 685 } 686 687 void OFileAccess::setInteractionHandler( const Reference< XInteractionHandler >& Handler ) 688 { 689 if( !mpEnvironment ) 690 { 691 mpEnvironment = new OCommandEnvironment(); 692 mxEnvironment = (XCommandEnvironment*)mpEnvironment; 693 } 694 mpEnvironment->setHandler( Handler ); 695 } 696 697 bool OFileAccess::createNewFile( const rtl::OUString & rParentURL, 698 const rtl::OUString & rTitle, 699 const Reference< XInputStream >& data ) 700 { 701 ucbhelper::Content aParentCnt( rParentURL, mxEnvironment ); 702 703 Sequence< ContentInfo > aInfo = aParentCnt.queryCreatableContentsInfo(); 704 sal_Int32 nCount = aInfo.getLength(); 705 if ( nCount == 0 ) 706 return false; 707 708 for ( sal_Int32 i = 0; i < nCount; ++i ) 709 { 710 const ContentInfo & rCurr = aInfo[i]; 711 if ( ( rCurr.Attributes 712 & ContentInfoAttribute::KIND_DOCUMENT ) && 713 ( rCurr.Attributes 714 & ContentInfoAttribute::INSERT_WITH_INPUTSTREAM ) ) 715 { 716 // Make sure the only required bootstrap property is 717 // "Title", 718 const Sequence< Property > & rProps = rCurr.Properties; 719 if ( rProps.getLength() != 1 ) 720 continue; 721 722 if ( !rProps[ 0 ].Name.equalsAsciiL( 723 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) 724 continue; 725 726 Sequence<rtl::OUString> aNames(1); 727 rtl::OUString* pNames = aNames.getArray(); 728 pNames[0] = rtl::OUString( 729 RTL_CONSTASCII_USTRINGPARAM( "Title" ) ); 730 Sequence< Any > aValues(1); 731 Any* pValues = aValues.getArray(); 732 pValues[0] = makeAny( rtl::OUString( rTitle ) ); 733 734 try 735 { 736 ucbhelper::Content aNew; 737 if ( aParentCnt.insertNewContent( 738 rCurr.Type, aNames, aValues, data, aNew ) ) 739 return true; // success. 740 else 741 continue; 742 } 743 catch ( CommandFailedException const & ) 744 { 745 // Interaction Handler already handled the 746 // error that has occurred... 747 continue; 748 } 749 } 750 } 751 752 return false; 753 } 754 755 void SAL_CALL OFileAccess::writeFile( const rtl::OUString& FileURL, 756 const Reference< XInputStream >& data ) 757 { 758 INetURLObject aURL( FileURL, INET_PROT_FILE ); 759 try 760 { 761 ucbhelper::Content aCnt( 762 aURL.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment ); 763 764 try 765 { 766 aCnt.writeStream( data, sal_True /* bReplaceExisting */ ); 767 } 768 catch ( CommandFailedException const & ) 769 { 770 // Interaction Handler already handled the error that has occurred... 771 } 772 } 773 catch ( ContentCreationException const & e ) 774 { 775 // Most probably file does not exist. Try to create. 776 if ( e.eError == ContentCreationError_CONTENT_CREATION_FAILED ) 777 { 778 INetURLObject aParentURLObj( aURL ); 779 if ( aParentURLObj.removeSegment() ) 780 { 781 String aParentURL 782 = aParentURLObj.GetMainURL( INetURLObject::NO_DECODE ); 783 784 // ensure all parent folders exist. 785 createFolder( aParentURL ); 786 787 // create the new file... 788 String aTitle 789 = aURL.getName( INetURLObject::LAST_SEGMENT, 790 true, 791 INetURLObject::DECODE_WITH_CHARSET ); 792 if ( createNewFile( aParentURL, aTitle, data ) ) 793 { 794 // success 795 return; 796 } 797 } 798 } 799 800 throw; 801 } 802 } 803 804 sal_Bool OFileAccess::isHidden( const ::rtl::OUString& FileURL ) 805 { 806 INetURLObject aURLObj( FileURL, INET_PROT_FILE ); 807 ucbhelper::Content aCnt( aURLObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment ); 808 Any aRetAny = aCnt.getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsHidden" ) ) ); 809 sal_Bool bRet = sal_False; 810 aRetAny >>= bRet; 811 return bRet; 812 } 813 814 void OFileAccess::setHidden( const ::rtl::OUString& FileURL, sal_Bool bHidden ) 815 { 816 INetURLObject aURLObj( FileURL, INET_PROT_FILE ); 817 ucbhelper::Content aCnt( aURLObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment ); 818 Any aAny; 819 aAny <<= bHidden; 820 aCnt.setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsHidden" ) ), aAny ); 821 } 822 823 //================================================================================================== 824 //================================================================================================== 825 //================================================================================================== 826 827 Reference< XInterface > SAL_CALL FileAccess_CreateInstance( const Reference< XComponentContext > & xCtx ) 828 { 829 return Reference < XInterface >( ( cppu::OWeakObject * ) new OFileAccess( xCtx ) ); 830 } 831 832 rtl::OUString FileAccess_getImplementationName() 833 { 834 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.ucb.SimpleFileAccess" ) ); 835 } 836 837 Sequence< rtl::OUString > FileAccess_getSupportedServiceNames() 838 { 839 static Sequence < rtl::OUString > *pNames = 0; 840 if( ! pNames ) 841 { 842 osl::MutexGuard guard( osl::Mutex::getGlobalMutex() ); 843 if( !pNames ) 844 { 845 static Sequence< rtl::OUString > seqNames(1); 846 seqNames.getArray()[0] = rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ); 847 pNames = &seqNames; 848 } 849 } 850 return *pNames; 851 } 852 853 struct ::cppu::ImplementationEntry g_component_entries [] = 854 { 855 { 856 FileAccess_CreateInstance, 857 FileAccess_getImplementationName, 858 FileAccess_getSupportedServiceNames, 859 ::cppu::createSingleComponentFactory, 860 0, 861 0 862 }, 863 { 0, 0, 0, 0, 0, 0 } 864 }; 865 866 } 867 868 //================================================================================================== 869 // Component exports 870 871 extern "C" 872 { 873 //================================================================================================== 874 FILEACCESS_DLLPUBLIC void SAL_CALL component_getImplementationEnvironment( 875 const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) 876 { 877 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; 878 } 879 //================================================================================================== 880 FILEACCESS_DLLPUBLIC void * SAL_CALL component_getFactory( 881 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) 882 { 883 return ::cppu::component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey, ::io_FileAccess::g_component_entries ); 884 } 885 } 886