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 27 /************************************************************************** 28 TODO 29 ************************************************************************** 30 31 *************************************************************************/ 32 #include <osl/diagnose.h> 33 #include "odma_contentprops.hxx" 34 #include <com/sun/star/ucb/XDynamicResultSet.hpp> 35 #include <com/sun/star/beans/PropertyAttribute.hpp> 36 #include <com/sun/star/beans/XPropertyAccess.hpp> 37 #include <com/sun/star/lang/IllegalAccessException.hpp> 38 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> 39 #include <com/sun/star/sdbc/XRow.hpp> 40 #include <com/sun/star/io/XOutputStream.hpp> 41 #include <com/sun/star/io/XActiveDataSink.hpp> 42 #include <com/sun/star/ucb/OpenCommandArgument2.hpp> 43 #include <com/sun/star/ucb/OpenMode.hpp> 44 #include <com/sun/star/ucb/XCommandInfo.hpp> 45 #include <com/sun/star/ucb/XPersistentPropertySet.hpp> 46 #include <ucbhelper/contentidentifier.hxx> 47 #include <ucbhelper/propertyvalueset.hxx> 48 #include <ucbhelper/cancelcommandexecution.hxx> 49 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> 50 #include <com/sun/star/ucb/MissingInputStreamException.hpp> 51 #include <com/sun/star/ucb/InsertCommandArgument.hpp> 52 #include <com/sun/star/ucb/MissingPropertiesException.hpp> 53 #include <com/sun/star/io/XActiveDataStreamer.hpp> 54 #include <com/sun/star/ucb/TransferInfo.hpp> 55 #include <com/sun/star/ucb/NameClash.hpp> 56 #include "odma_content.hxx" 57 #include "odma_provider.hxx" 58 #include "odma_resultset.hxx" 59 #include "odma_inputstream.hxx" 60 #include <ucbhelper/content.hxx> 61 #include <com/sun/star/uno/Exception.hpp> 62 #include <rtl/ref.hxx> 63 #include <osl/file.hxx> 64 65 using namespace com::sun::star; 66 using namespace odma; 67 68 //========================================================================= 69 //========================================================================= 70 // 71 // Content Implementation. 72 // 73 //========================================================================= 74 //========================================================================= 75 76 Content::Content( const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 77 ContentProvider* pProvider, 78 const uno::Reference< ucb::XContentIdentifier >& Identifier, 79 const ::rtl::Reference<ContentProperties>& _rProps) 80 : ContentImplHelper( rxSMgr, pProvider, Identifier ) 81 ,m_aProps(_rProps) 82 ,m_pProvider(pProvider) 83 ,m_pContent(NULL) 84 { 85 OSL_ENSURE(m_aProps.is(),"No valid ContentPropeties!"); 86 } 87 88 //========================================================================= 89 // virtual 90 Content::~Content() 91 { 92 delete m_pContent; 93 } 94 95 //========================================================================= 96 // 97 // XInterface methods. 98 // 99 //========================================================================= 100 101 // virtual 102 void SAL_CALL Content::acquire() throw() 103 { 104 ContentImplHelper::acquire(); 105 } 106 107 //========================================================================= 108 // virtual 109 void SAL_CALL Content::release() throw() 110 { 111 ContentImplHelper::release(); 112 } 113 114 //========================================================================= 115 // virtual 116 uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) 117 throw ( uno::RuntimeException ) 118 { 119 uno::Any aRet; 120 121 // @@@ Add support for additional interfaces. 122 #if 0 123 aRet = cppu::queryInterface( rType, 124 static_cast< yyy::Xxxxxxxxx * >( this ) ); 125 #endif 126 127 return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType ); 128 } 129 130 //========================================================================= 131 // 132 // XTypeProvider methods. 133 // 134 //========================================================================= 135 136 XTYPEPROVIDER_COMMON_IMPL( Content ); 137 138 //========================================================================= 139 // virtual 140 uno::Sequence< uno::Type > SAL_CALL Content::getTypes() 141 throw( uno::RuntimeException ) 142 { 143 // @@@ Add own interfaces. 144 145 static cppu::OTypeCollection* pCollection = 0; 146 147 if ( !pCollection ) 148 { 149 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 150 if ( !pCollection ) 151 { 152 static cppu::OTypeCollection aCollection( 153 CPPU_TYPE_REF( lang::XTypeProvider ), 154 CPPU_TYPE_REF( lang::XServiceInfo ), 155 CPPU_TYPE_REF( lang::XComponent ), 156 CPPU_TYPE_REF( ucb::XContent ), 157 CPPU_TYPE_REF( ucb::XCommandProcessor ), 158 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), 159 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), 160 CPPU_TYPE_REF( beans::XPropertyContainer ), 161 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), 162 CPPU_TYPE_REF( container::XChild ) ); 163 pCollection = &aCollection; 164 } 165 } 166 167 return (*pCollection).getTypes(); 168 } 169 170 //========================================================================= 171 // 172 // XServiceInfo methods. 173 // 174 //========================================================================= 175 176 // virtual 177 rtl::OUString SAL_CALL Content::getImplementationName() 178 throw( uno::RuntimeException ) 179 { 180 // @@@ Adjust implementation name. Keep the prefix "com.sun.star.comp."! 181 return rtl::OUString::createFromAscii( "com.sun.star.comp.odma.Content" ); 182 } 183 184 //========================================================================= 185 // virtual 186 uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames() 187 throw( uno::RuntimeException ) 188 { 189 // @@@ Adjust macro name. 190 uno::Sequence< rtl::OUString > aSNS( 1 ); 191 aSNS.getArray()[ 0 ] 192 = rtl::OUString::createFromAscii( ODMA_CONTENT_SERVICE_NAME ); 193 return aSNS; 194 } 195 196 //========================================================================= 197 // 198 // XContent methods. 199 // 200 //========================================================================= 201 202 // virtual 203 rtl::OUString SAL_CALL Content::getContentType() 204 throw( uno::RuntimeException ) 205 { 206 // @@@ Adjust macro name ( def in odma_provider.hxx ). 207 return rtl::OUString::createFromAscii( ODMA_CONTENT_TYPE ); 208 } 209 210 //========================================================================= 211 // 212 // XCommandProcessor methods. 213 // 214 //========================================================================= 215 216 // virtual 217 uno::Any SAL_CALL Content::execute( 218 const ucb::Command& aCommand, 219 sal_Int32 /*CommandId*/, 220 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 221 throw( uno::Exception, 222 ucb::CommandAbortedException, 223 uno::RuntimeException ) 224 { 225 uno::Any aRet; 226 227 if ( aCommand.Name.equalsAsciiL( 228 RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) ) 229 { 230 ////////////////////////////////////////////////////////////////// 231 // getPropertyValues 232 ////////////////////////////////////////////////////////////////// 233 234 uno::Sequence< beans::Property > Properties; 235 if ( !( aCommand.Argument >>= Properties ) ) 236 { 237 OSL_ENSURE( sal_False, "Wrong argument type!" ); 238 ucbhelper::cancelCommandExecution( 239 uno::makeAny( lang::IllegalArgumentException( 240 rtl::OUString(), 241 static_cast< cppu::OWeakObject * >( this ), 242 -1 ) ), 243 Environment ); 244 // Unreachable 245 } 246 247 aRet <<= getPropertyValues( Properties, Environment ); 248 } 249 else if ( aCommand.Name.equalsAsciiL( 250 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) ) 251 { 252 ////////////////////////////////////////////////////////////////// 253 // setPropertyValues 254 ////////////////////////////////////////////////////////////////// 255 256 uno::Sequence< beans::PropertyValue > aProperties; 257 if ( !( aCommand.Argument >>= aProperties ) ) 258 { 259 OSL_ENSURE( sal_False, "Wrong argument type!" ); 260 ucbhelper::cancelCommandExecution( 261 uno::makeAny( lang::IllegalArgumentException( 262 rtl::OUString(), 263 static_cast< cppu::OWeakObject * >( this ), 264 -1 ) ), 265 Environment ); 266 // Unreachable 267 } 268 269 if ( !aProperties.getLength() ) 270 { 271 OSL_ENSURE( sal_False, "No properties!" ); 272 ucbhelper::cancelCommandExecution( 273 uno::makeAny( lang::IllegalArgumentException( 274 rtl::OUString(), 275 static_cast< cppu::OWeakObject * >( this ), 276 -1 ) ), 277 Environment ); 278 // Unreachable 279 } 280 281 aRet <<= setPropertyValues( aProperties, Environment ); 282 } 283 else if ( aCommand.Name.equalsAsciiL( 284 RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) ) 285 { 286 ////////////////////////////////////////////////////////////////// 287 // getPropertySetInfo 288 ////////////////////////////////////////////////////////////////// 289 290 // Note: Implemented by base class. 291 aRet <<= getPropertySetInfo( Environment ); 292 } 293 else if ( aCommand.Name.equalsAsciiL( 294 RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) ) 295 { 296 ////////////////////////////////////////////////////////////////// 297 // getCommandInfo 298 ////////////////////////////////////////////////////////////////// 299 300 // Note: Implemented by base class. 301 aRet <<= getCommandInfo( Environment ); 302 } 303 else if ( aCommand.Name.equalsAsciiL( 304 RTL_CONSTASCII_STRINGPARAM( "open" ) ) ) 305 { 306 ucb::OpenCommandArgument2 aOpenCommand; 307 if ( !( aCommand.Argument >>= aOpenCommand ) ) 308 { 309 OSL_ENSURE( sal_False, "Wrong argument type!" ); 310 ucbhelper::cancelCommandExecution( 311 uno::makeAny( lang::IllegalArgumentException( 312 rtl::OUString(), 313 static_cast< cppu::OWeakObject * >( this ), 314 -1 ) ), 315 Environment ); 316 // Unreachable 317 } 318 319 sal_Bool bOpenFolder = 320 ( ( aOpenCommand.Mode == ucb::OpenMode::ALL ) || 321 ( aOpenCommand.Mode == ucb::OpenMode::FOLDERS ) || 322 ( aOpenCommand.Mode == ucb::OpenMode::DOCUMENTS ) ); 323 324 if ( bOpenFolder) 325 { 326 // open as folder - return result set 327 328 uno::Reference< ucb::XDynamicResultSet > xSet 329 = new DynamicResultSet( m_xSMgr, 330 this, 331 aOpenCommand, 332 Environment ); 333 aRet <<= xSet; 334 } 335 336 if ( aOpenCommand.Sink.is() ) 337 { 338 // Open document - supply document data stream. 339 340 // Check open mode 341 if ( ( aOpenCommand.Mode 342 == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) || 343 ( aOpenCommand.Mode 344 == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) ) 345 { 346 // Unsupported. 347 ucbhelper::cancelCommandExecution( 348 uno::makeAny( ucb::UnsupportedOpenModeException( 349 rtl::OUString(), 350 static_cast< cppu::OWeakObject * >( this ), 351 sal_Int16( aOpenCommand.Mode ) ) ), 352 Environment ); 353 // Unreachable 354 } 355 356 357 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 358 rtl::OUString sFileURL = openDoc(); 359 delete m_pContent; 360 m_pContent = new ::ucbhelper::Content(sFileURL,NULL); 361 if(!m_pContent->isDocument()) 362 { 363 rtl::OUString sErrorMsg(RTL_CONSTASCII_USTRINGPARAM("File: ")); 364 sErrorMsg += sFileURL; 365 sErrorMsg += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" could not be found.")); 366 ucbhelper::cancelCommandExecution( 367 uno::makeAny( io::IOException( 368 sErrorMsg, 369 static_cast< cppu::OWeakObject * >( this )) ), 370 Environment ); 371 } 372 373 uno::Reference< io::XOutputStream > xOut 374 = uno::Reference< io::XOutputStream >( 375 aOpenCommand.Sink, uno::UNO_QUERY ); 376 if ( xOut.is() ) 377 { 378 // @@@ PUSH: write data into xOut 379 m_pContent->openStream(xOut); 380 } 381 else 382 { 383 uno::Reference< io::XActiveDataSink > xDataSink 384 = uno::Reference< io::XActiveDataSink >( 385 aOpenCommand.Sink, uno::UNO_QUERY ); 386 if ( xDataSink.is() ) 387 { 388 // @@@ PULL: wait for client read 389 uno::Reference< io::XInputStream > xIn; 390 try 391 { 392 xIn = m_pContent->openStream(); 393 } 394 catch(uno::Exception&) 395 { 396 OSL_ENSURE(0,"Exception occured while creating the file content!"); 397 } 398 xDataSink->setInputStream( xIn ); 399 } 400 else 401 { 402 uno::Reference< io::XActiveDataStreamer > activeDataStreamer( aOpenCommand.Sink,uno::UNO_QUERY ); 403 if(activeDataStreamer.is()) 404 { 405 activeDataStreamer->setStream(new OOdmaStream(m_pContent,getContentProvider(),m_aProps)); 406 m_pContent = NULL; // don't delete here because the stream is now the owner 407 } 408 else 409 { 410 // Note: aOpenCommand.Sink may contain an XStream 411 // implementation. Support for this type of 412 // sink is optional... 413 ucbhelper::cancelCommandExecution( 414 uno::makeAny( ucb::UnsupportedDataSinkException( 415 rtl::OUString(), 416 static_cast< cppu::OWeakObject * >( this ), 417 aOpenCommand.Sink ) ), 418 Environment ); 419 // Unreachable 420 } 421 } 422 } 423 } 424 } 425 else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "close" ) ) ) 426 { 427 getContentProvider()->closeDocument(m_aProps->m_sDocumentId); 428 } 429 else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "delete" ) ) ) 430 { 431 ////////////////////////////////////////////////////////////////// 432 // delete 433 ////////////////////////////////////////////////////////////////// 434 435 // Remove own and all children's Additional Core Properties. 436 removeAdditionalPropertySet( sal_True ); 437 // Remove own and all childrens(!) persistent data. 438 if(!getContentProvider()->deleteDocument(m_aProps)) 439 ucbhelper::cancelCommandExecution( 440 uno::makeAny( lang::IllegalArgumentException( 441 rtl::OUString(), 442 static_cast< cppu::OWeakObject * >( this ), 443 -1 ) ), 444 Environment ); 445 } 446 else if ( aCommand.Name.equalsAsciiL( 447 RTL_CONSTASCII_STRINGPARAM( "insert" ) ) ) 448 { 449 ////////////////////////////////////////////////////////////////// 450 // insert 451 ////////////////////////////////////////////////////////////////// 452 453 ucb::InsertCommandArgument arg; 454 if ( !( aCommand.Argument >>= arg ) ) 455 { 456 OSL_ENSURE( sal_False, "Wrong argument type!" ); 457 ucbhelper::cancelCommandExecution( 458 uno::makeAny( lang::IllegalArgumentException( 459 rtl::OUString(), 460 static_cast< cppu::OWeakObject * >( this ), 461 -1 ) ), 462 Environment ); 463 // Unreachable 464 } 465 466 insert( arg.Data, arg.ReplaceExisting, Environment ); 467 } 468 else if( ! aCommand.Name.compareToAscii( "transfer" ) ) 469 { 470 ucb::TransferInfo aTransferInfo; 471 if( ! ( aCommand.Argument >>= aTransferInfo ) ) 472 { 473 OSL_ENSURE( sal_False, "Wrong argument type!" ); 474 ucbhelper::cancelCommandExecution( 475 uno::makeAny( lang::IllegalArgumentException( 476 rtl::OUString(), 477 static_cast< cppu::OWeakObject * >( this ), 478 -1 ) ), 479 Environment ); 480 // Unreachable 481 } 482 ::rtl::Reference<ContentProperties> aProp = m_aProps; 483 if(aProp->m_bIsFolder) 484 { 485 aProp = getContentProvider()->getContentPropertyWithTitle(aTransferInfo.NewTitle); 486 if(!aProp.is()) 487 aProp = getContentProvider()->getContentPropertyWithSavedAsName(aTransferInfo.NewTitle); 488 sal_Bool bError = !aProp.is(); 489 if(bError) 490 { 491 sal_Char* pExtension = NULL; 492 ::rtl::OString sExt; 493 sal_Int32 nPos = aTransferInfo.NewTitle.lastIndexOf('.'); 494 if(nPos != -1) 495 { 496 sExt = ::rtl::OUStringToOString(aTransferInfo.NewTitle.copy(nPos+1),RTL_TEXTENCODING_ASCII_US); 497 if(sExt.equalsIgnoreAsciiCase("txt")) 498 pExtension = ODM_FORMAT_TEXT; 499 else if(sExt.equalsIgnoreAsciiCase("rtf")) 500 pExtension = ODM_FORMAT_RTF; 501 else if(sExt.equalsIgnoreAsciiCase("ps")) 502 pExtension = ODM_FORMAT_PS; 503 else 504 pExtension = const_cast<sal_Char*>(sExt.getStr()); 505 } 506 else 507 pExtension = ODM_FORMAT_TEXT; 508 509 sal_Char* lpszNewDocId = new sal_Char[ODM_DOCID_MAX]; 510 void *pData = NULL; 511 DWORD dwFlags = ODM_SILENT; 512 ODMSTATUS odm = NODMSaveAsEx(ContentProvider::getHandle(), 513 NULL, // means it is saved the first time 514 lpszNewDocId, 515 pExtension, 516 NULL, // no callback function here 517 pData, 518 &dwFlags); 519 520 // check if we have to call the DMS dialog 521 if(odm == ODM_E_USERINT) 522 { 523 dwFlags = 0; 524 odm = NODMSaveAsEx(ContentProvider::getHandle(), 525 NULL, // means it is saved the first time 526 lpszNewDocId, 527 pExtension, 528 NULL, // no callback function here 529 pData, 530 &dwFlags); 531 } 532 bError = odm != ODM_SUCCESS; 533 if(!bError) 534 { 535 aProp = new ContentProperties(); 536 aProp->m_sDocumentId = ::rtl::OString(lpszNewDocId); 537 aProp->m_sContentType = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODMA_CONTENT_TYPE)); 538 aProp->m_sSavedAsName = aTransferInfo.NewTitle; 539 getContentProvider()->append(aProp); 540 541 // now set the title 542 WORD nDocInfo = ODM_NAME; 543 ::rtl::OUString sFileName = aTransferInfo.NewTitle; 544 sal_Int32 nIndex = aTransferInfo.NewTitle.lastIndexOf( sal_Unicode('.') ); 545 if(nIndex != -1) 546 sFileName = aTransferInfo.NewTitle.copy(0,nIndex); 547 548 ::rtl::OString sDocInfoValue = ::rtl::OUStringToOString(sFileName,RTL_TEXTENCODING_ASCII_US); 549 odm = NODMSetDocInfo( ContentProvider::getHandle(), 550 lpszNewDocId, 551 nDocInfo, 552 const_cast<sal_Char*>(sDocInfoValue.getStr()) 553 ); 554 555 } 556 else if ( odm == ODM_E_CANCEL) 557 NODMActivate(ContentProvider::getHandle(), 558 ODM_DELETE, 559 lpszNewDocId); 560 561 delete [] lpszNewDocId; 562 } 563 if(bError) 564 ucbhelper::cancelCommandExecution( 565 uno::makeAny( lang::IllegalArgumentException( 566 rtl::OUString(), 567 static_cast< cppu::OWeakObject * >( this ), 568 -1 ) ), 569 Environment ); 570 } 571 rtl::OUString sFileURL = ContentProvider::openDoc(aProp); 572 573 sal_Int32 nLastIndex = sFileURL.lastIndexOf( sal_Unicode('/') ); 574 ::ucbhelper::Content aContent(sFileURL.copy(0,nLastIndex),NULL); 575 // aTransferInfo.NameClash = ucb::NameClash::OVERWRITE; 576 aTransferInfo.NewTitle = sFileURL.copy( 1 + nLastIndex ); 577 aContent.executeCommand(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("transfer")),uno::makeAny(aTransferInfo)); 578 getContentProvider()->saveDocument(aProp->m_sDocumentId); 579 } 580 else 581 { 582 ////////////////////////////////////////////////////////////////// 583 // Unsupported command 584 ////////////////////////////////////////////////////////////////// 585 586 OSL_ENSURE( sal_False, "Content::execute - unsupported command!" ); 587 588 ucbhelper::cancelCommandExecution( 589 uno::makeAny( ucb::UnsupportedCommandException( 590 rtl::OUString(), 591 static_cast< cppu::OWeakObject * >( this ) ) ), 592 Environment ); 593 // Unreachable 594 } 595 596 return aRet; 597 } 598 599 //========================================================================= 600 // virtual 601 void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ ) 602 throw( uno::RuntimeException ) 603 { 604 // @@@ Implement logic to abort running commands, if this makes 605 // sense for your content. 606 } 607 608 //========================================================================= 609 // 610 // Non-interface methods. 611 // 612 //========================================================================= 613 614 // virtual 615 ::rtl::OUString Content::getParentURL() 616 { 617 ::rtl::OUString sURL = m_xIdentifier->getContentIdentifier(); 618 619 // @@@ Extract URL of parent from aURL and return it... 620 static ::rtl::OUString sScheme1(RTL_CONSTASCII_USTRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT "/")); 621 static ::rtl::OUString sScheme2(RTL_CONSTASCII_USTRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT)); 622 if(sURL == sScheme1 || sURL == sScheme2) 623 sURL = ::rtl::OUString(); 624 else 625 sURL = sScheme1; 626 627 return sURL; 628 } 629 630 //========================================================================= 631 // static 632 uno::Reference< sdbc::XRow > Content::getPropertyValues( 633 const uno::Reference< lang::XMultiServiceFactory >& rSMgr, 634 const uno::Sequence< beans::Property >& rProperties, 635 const rtl::Reference<ContentProperties>& rData, 636 const rtl::Reference< ::ucbhelper::ContentProviderImplHelper >& rProvider, 637 const rtl::OUString& rContentId ) 638 { 639 // Note: Empty sequence means "get values of all supported properties". 640 641 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow 642 = new ::ucbhelper::PropertyValueSet( rSMgr ); 643 644 sal_Int32 nCount = rProperties.getLength(); 645 if ( nCount ) 646 { 647 uno::Reference< beans::XPropertySet > xAdditionalPropSet; 648 sal_Bool bTriedToGetAdditonalPropSet = sal_False; 649 650 const beans::Property* pProps = rProperties.getConstArray(); 651 for ( sal_Int32 n = 0; n < nCount; ++n ) 652 { 653 const beans::Property& rProp = pProps[ n ]; 654 655 // Process Core properties. 656 657 if ( rProp.Name.equalsAsciiL( 658 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) 659 { 660 xRow->appendString ( rProp, rData->m_sContentType ); 661 } 662 else if ( rProp.Name.equalsAsciiL( 663 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) 664 { 665 xRow->appendString ( rProp, rData->m_sTitle ); 666 } 667 else if ( rProp.Name.equalsAsciiL( 668 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) 669 { 670 xRow->appendBoolean( rProp, rData->m_bIsDocument ); 671 } 672 else if ( rProp.Name.equalsAsciiL( 673 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) 674 { 675 xRow->appendBoolean( rProp, rData->m_bIsFolder ); 676 } 677 else if ( rProp.Name.equalsAsciiL( 678 RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) ) 679 { 680 xRow->appendTimestamp( rProp, rData->m_aDateCreated ); 681 } 682 else if ( rProp.Name.equalsAsciiL( 683 RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ) 684 { 685 xRow->appendTimestamp( rProp, rData->m_aDateModified ); 686 } 687 else if ( rProp.Name.equalsAsciiL( 688 RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) ) 689 { 690 xRow->appendBoolean( rProp, rData->m_bIsReadOnly ); 691 } 692 else if ( rProp.Name.equalsAsciiL( 693 RTL_CONSTASCII_STRINGPARAM( "Author" ) ) ) 694 { 695 xRow->appendString ( rProp, rData->m_sAuthor ); 696 } 697 else if ( rProp.Name.equalsAsciiL( 698 RTL_CONSTASCII_STRINGPARAM( "Subject" ) ) ) 699 { 700 xRow->appendString ( rProp, rData->m_sSubject ); 701 } 702 else if ( rProp.Name.equalsAsciiL( 703 RTL_CONSTASCII_STRINGPARAM( "Keywords" ) ) ) 704 { 705 xRow->appendString ( rProp, rData->m_sKeywords ); 706 } 707 else 708 { 709 // @@@ Note: If your data source supports adding/removing 710 // properties, you should implement the interface 711 // XPropertyContainer by yourself and supply your own 712 // logic here. The base class uses the service 713 // "com.sun.star.ucb.Store" to maintain Additional Core 714 // properties. But using server functionality is preferred! 715 716 // Not a Core Property! Maybe it's an Additional Core Property?! 717 718 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) 719 { 720 xAdditionalPropSet 721 = uno::Reference< beans::XPropertySet >( 722 rProvider->getAdditionalPropertySet( rContentId, 723 sal_False ), 724 uno::UNO_QUERY ); 725 bTriedToGetAdditonalPropSet = sal_True; 726 } 727 728 if ( xAdditionalPropSet.is() ) 729 { 730 if ( !xRow->appendPropertySetValue( 731 xAdditionalPropSet, 732 rProp ) ) 733 { 734 // Append empty entry. 735 xRow->appendVoid( rProp ); 736 } 737 } 738 else 739 { 740 // Append empty entry. 741 xRow->appendVoid( rProp ); 742 } 743 } 744 } 745 } 746 else 747 { 748 // Append all Core Properties. 749 xRow->appendString ( 750 beans::Property( rtl::OUString::createFromAscii( "ContentType" ), 751 -1, 752 getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 753 beans::PropertyAttribute::BOUND 754 | beans::PropertyAttribute::READONLY ), 755 rData->m_sContentType ); 756 xRow->appendString ( 757 beans::Property( rtl::OUString::createFromAscii( "Title" ), 758 -1, 759 getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 760 beans::PropertyAttribute::BOUND ), 761 rData->m_sTitle ); 762 xRow->appendBoolean( 763 beans::Property( rtl::OUString::createFromAscii( "IsDocument" ), 764 -1, 765 getCppuBooleanType(), 766 beans::PropertyAttribute::BOUND 767 | beans::PropertyAttribute::READONLY ), 768 rData->m_bIsDocument ); 769 xRow->appendBoolean( 770 beans::Property( rtl::OUString::createFromAscii( "IsFolder" ), 771 -1, 772 getCppuBooleanType(), 773 beans::PropertyAttribute::BOUND 774 | beans::PropertyAttribute::READONLY ), 775 rData->m_bIsFolder ); 776 777 // @@@ Append other properties supported directly. 778 xRow->appendTimestamp( 779 beans::Property( rtl::OUString::createFromAscii( "DateCreated" ), 780 -1, 781 getCppuType(static_cast< const util::DateTime * >( 0 ) ), 782 beans::PropertyAttribute::BOUND 783 | beans::PropertyAttribute::READONLY ), 784 rData->m_aDateCreated ); 785 xRow->appendTimestamp( 786 beans::Property( rtl::OUString::createFromAscii( "DateModified" ), 787 -1, 788 getCppuType(static_cast< const util::DateTime * >( 0 ) ), 789 beans::PropertyAttribute::BOUND 790 | beans::PropertyAttribute::READONLY ), 791 rData->m_aDateModified ); 792 xRow->appendBoolean( 793 beans::Property( rtl::OUString::createFromAscii( "IsReadOnly" ), 794 -1, 795 getCppuBooleanType(), 796 beans::PropertyAttribute::BOUND 797 | beans::PropertyAttribute::READONLY ), 798 rData->m_bIsReadOnly ); 799 xRow->appendString ( 800 beans::Property( rtl::OUString::createFromAscii( "Author" ), 801 -1, 802 getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 803 beans::PropertyAttribute::BOUND ), 804 rData->m_sAuthor ); 805 xRow->appendString ( 806 beans::Property( rtl::OUString::createFromAscii( "Subject" ), 807 -1, 808 getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 809 beans::PropertyAttribute::BOUND ), 810 rData->m_sSubject ); 811 xRow->appendString ( 812 beans::Property( rtl::OUString::createFromAscii( "Keywords" ), 813 -1, 814 getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 815 beans::PropertyAttribute::BOUND ), 816 rData->m_sKeywords ); 817 818 // @@@ Note: If your data source supports adding/removing 819 // properties, you should implement the interface 820 // XPropertyContainer by yourself and supply your own 821 // logic here. The base class uses the service 822 // "com.sun.star.ucb.Store" to maintain Additional Core 823 // properties. But using server functionality is preferred! 824 825 // Append all Additional Core Properties. 826 827 uno::Reference< beans::XPropertySet > xSet( 828 rProvider->getAdditionalPropertySet( rContentId, sal_False ), 829 uno::UNO_QUERY ); 830 xRow->appendPropertySet( xSet ); 831 } 832 833 return uno::Reference< sdbc::XRow >( xRow.get() ); 834 } 835 836 //========================================================================= 837 uno::Reference< sdbc::XRow > Content::getPropertyValues( 838 const uno::Sequence< beans::Property >& rProperties, 839 const uno::Reference< ucb::XCommandEnvironment >& /*xEnv*/ ) 840 { 841 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 842 return getPropertyValues( m_xSMgr, 843 rProperties, 844 m_aProps, 845 rtl::Reference< 846 ::ucbhelper::ContentProviderImplHelper >( 847 m_xProvider.get() ), 848 m_xIdentifier->getContentIdentifier() ); 849 } 850 851 //========================================================================= 852 uno::Sequence< uno::Any > Content::setPropertyValues( 853 const uno::Sequence< beans::PropertyValue >& rValues, 854 const uno::Reference< ucb::XCommandEnvironment >& /*xEnv*/ ) 855 { 856 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 857 858 uno::Sequence< uno::Any > aRet( rValues.getLength() ); 859 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() ); 860 sal_Int32 nChanged = 0; 861 862 beans::PropertyChangeEvent aEvent; 863 aEvent.Source = static_cast< cppu::OWeakObject * >( this ); 864 aEvent.Further = sal_False; 865 // aEvent.PropertyName = 866 aEvent.PropertyHandle = -1; 867 // aEvent.OldValue = 868 // aEvent.NewValue = 869 870 const beans::PropertyValue* pValues = rValues.getConstArray(); 871 sal_Int32 nCount = rValues.getLength(); 872 873 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet; 874 sal_Bool bTriedToGetAdditonalPropSet = sal_False; 875 876 for ( sal_Int32 n = 0; n < nCount; ++n ) 877 { 878 const beans::PropertyValue& rValue = pValues[ n ]; 879 880 if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) 881 { 882 changePropertyValue(rValue,n,m_aProps->m_sTitle,nChanged,aRet,aChanges); 883 } 884 else if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Author") ) ) 885 { 886 changePropertyValue(rValue,n,m_aProps->m_sAuthor,nChanged,aRet,aChanges); 887 } 888 else if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Keywords") ) ) 889 { 890 changePropertyValue(rValue,n,m_aProps->m_sKeywords,nChanged,aRet,aChanges); 891 } 892 else if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "Subject") ) ) 893 { 894 changePropertyValue(rValue,n,m_aProps->m_sSubject,nChanged,aRet,aChanges); 895 } 896 else if ( rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) || 897 rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) || 898 rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) || 899 rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) || 900 rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) || 901 rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) ) 902 { 903 // Read-only property! 904 aRet[ n ] <<= lang::IllegalAccessException( 905 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 906 "Property is read-only!") ), 907 static_cast< cppu::OWeakObject * >( this ) ); 908 } 909 else 910 { 911 // @@@ Note: If your data source supports adding/removing 912 // properties, you should implement the interface 913 // XPropertyContainer by yourself and supply your own 914 // logic here. The base class uses the service 915 // "com.sun.star.ucb.Store" to maintain Additional Core 916 // properties. But using server functionality is preferred! 917 918 // Not a Core Property! Maybe it's an Additional Core Property?! 919 920 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) 921 { 922 xAdditionalPropSet = getAdditionalPropertySet( sal_False ); 923 bTriedToGetAdditonalPropSet = sal_True; 924 } 925 926 if ( xAdditionalPropSet.is() ) 927 { 928 try 929 { 930 uno::Any aOldValue 931 = xAdditionalPropSet->getPropertyValue( rValue.Name ); 932 if ( aOldValue != rValue.Value ) 933 { 934 xAdditionalPropSet->setPropertyValue( 935 rValue.Name, rValue.Value ); 936 937 aEvent.PropertyName = rValue.Name; 938 aEvent.OldValue = aOldValue; 939 aEvent.NewValue = rValue.Value; 940 941 aChanges.getArray()[ nChanged ] = aEvent; 942 nChanged++; 943 } 944 else 945 { 946 // Old value equals new value. No error! 947 } 948 } 949 catch ( beans::UnknownPropertyException const & e ) 950 { 951 aRet[ n ] <<= e; 952 } 953 catch ( lang::WrappedTargetException const & e ) 954 { 955 aRet[ n ] <<= e; 956 } 957 catch ( beans::PropertyVetoException const & e ) 958 { 959 aRet[ n ] <<= e; 960 } 961 catch ( lang::IllegalArgumentException const & e ) 962 { 963 aRet[ n ] <<= e; 964 } 965 } 966 else 967 { 968 aRet[ n ] <<= uno::Exception( 969 rtl::OUString::createFromAscii( 970 "No property set for storing the value!" ), 971 static_cast< cppu::OWeakObject * >( this ) ); 972 } 973 } 974 } 975 976 if ( nChanged > 0 ) 977 { 978 // @@@ Save changes. 979 // storeData(); 980 981 aGuard.clear(); 982 aChanges.realloc( nChanged ); 983 notifyPropertiesChange( aChanges ); 984 } 985 986 return aRet; 987 } 988 989 #if 0 990 //========================================================================= 991 void Content::queryChildren( ContentRefList& rChildren ) 992 { 993 // @@@ Adapt method to your URL scheme... 994 995 // Obtain a list with a snapshot of all currently instanciated contents 996 // from provider and extract the contents which are direct children 997 // of this content. 998 999 ::ucbhelper::ContentRefList aAllContents; 1000 m_xProvider->queryExistingContents( aAllContents ); 1001 1002 OUString aURL = m_xIdentifier->getContentIdentifier(); 1003 sal_Int32 nPos = aURL.lastIndexOf( '/' ); 1004 1005 if ( nPos != ( aURL.getLength() - 1 ) ) 1006 { 1007 // No trailing slash found. Append. 1008 aURL += OUString::createFromAscii( "/" ); 1009 } 1010 1011 sal_Int32 nLen = aURL.getLength(); 1012 1013 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); 1014 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); 1015 1016 while ( it != end ) 1017 { 1018 ::ucbhelper::ContentImplHelperRef xChild = (*it); 1019 OUString aChildURL = xChild->getIdentifier()->getContentIdentifier(); 1020 1021 // Is aURL a prefix of aChildURL? 1022 if ( ( aChildURL.getLength() > nLen ) && 1023 ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) 1024 { 1025 sal_Int32 nPos = nLen; 1026 nPos = aChildURL.indexOf( '/', nPos ); 1027 1028 if ( ( nPos == -1 ) || 1029 ( nPos == ( aChildURL.getLength() - 1 ) ) ) 1030 { 1031 // No further slashes / only a final slash. It's a child! 1032 rChildren.push_back( 1033 ContentRef( 1034 static_cast< Content * >( xChild.get() ) ) ); 1035 } 1036 } 1037 ++it; 1038 } 1039 } 1040 #endif 1041 //========================================================================= 1042 void Content::insert( 1043 const uno::Reference< io::XInputStream > & xInputStream, 1044 sal_Bool bReplaceExisting, 1045 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 1046 throw( uno::Exception ) 1047 { 1048 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 1049 1050 // Check, if all required properties were set. 1051 if ( !m_aProps->m_sTitle.getLength()) 1052 { 1053 OSL_ENSURE( sal_False, "Content::insert - property value missing!" ); 1054 1055 uno::Sequence< rtl::OUString > aProps( 1 ); 1056 aProps[ 0 ] = rtl::OUString::createFromAscii( "zzzz" ); 1057 ucbhelper::cancelCommandExecution( 1058 uno::makeAny( ucb::MissingPropertiesException( 1059 rtl::OUString(), 1060 static_cast< cppu::OWeakObject * >( this ), 1061 aProps ) ), 1062 Environment ); 1063 // Unreachable 1064 } 1065 1066 if ( !xInputStream.is() ) 1067 { 1068 OSL_ENSURE( sal_False, "Content::insert - No data stream!" ); 1069 1070 ucbhelper::cancelCommandExecution( 1071 uno::makeAny( ucb::MissingInputStreamException( 1072 rtl::OUString(), 1073 static_cast< cppu::OWeakObject * >( this ) ) ), 1074 Environment ); 1075 // Unreachable 1076 } 1077 1078 // Assemble new content identifier... 1079 1080 // uno::Reference< ucb::XContentIdentifier > xId = ...; 1081 1082 // Fail, if a resource with given id already exists. 1083 if ( !bReplaceExisting ) // && hasData( m_xIdentifier ) ) 1084 { 1085 ucbhelper::cancelCommandExecution( 1086 uno::makeAny( ucb::UnsupportedCommandException( 1087 rtl::OUString(), 1088 static_cast< cppu::OWeakObject * >( this ) ) ), 1089 Environment ); 1090 // ucbhelper::cancelCommandExecution( 1091 // ucb::IOErrorCode_ALREADY_EXISTING, 1092 // Environment, 1093 // uno::makeAny(static_cast< cppu::OWeakObject * >( this )) 1094 // ); 1095 // Unreachable 1096 } 1097 1098 // m_xIdentifier = xId; 1099 1100 // @@@ 1101 // storeData(); 1102 1103 aGuard.clear(); 1104 inserted(); 1105 } 1106 #if 0 1107 //========================================================================= 1108 void Content::destroy( sal_Bool bDeletePhysical ) 1109 throw( uno::Exception ) 1110 { 1111 // @@@ take care about bDeletePhysical -> trashcan support 1112 1113 uno::Reference< ucb::XContent > xThis = this; 1114 1115 deleted(); 1116 1117 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1118 1119 // Process instanciated children... 1120 1121 ContentRefList aChildren; 1122 queryChildren( aChildren ); 1123 1124 ContentRefList::const_iterator it = aChildren.begin(); 1125 ContentRefList::const_iterator end = aChildren.end(); 1126 1127 while ( it != end ) 1128 { 1129 (*it)->destroy( bDeletePhysical ); 1130 ++it; 1131 } 1132 } 1133 #endif 1134 1135 // ----------------------------------------------------------------------------- 1136 ::rtl::OUString Content::openDoc() 1137 { 1138 OSL_ENSURE(m_aProps.is(),"No valid content properties!"); 1139 return ContentProvider::openDoc(m_aProps); 1140 } 1141 // ----------------------------------------------------------------------------- 1142 void Content::changePropertyValue(const beans::PropertyValue& _rValue, 1143 sal_Int32 _rnCurrentPos, 1144 ::rtl::OUString& _rsMemberValue, 1145 sal_Int32& _rnChanged, 1146 uno::Sequence< uno::Any >& _rRet, 1147 uno::Sequence< beans::PropertyChangeEvent >& _rChanges) throw (beans::IllegalTypeException) 1148 { 1149 rtl::OUString sNewValue; 1150 sal_Bool bError = sal_False; 1151 if ( _rValue.Value >>= sNewValue ) 1152 { 1153 if ( sNewValue != _rsMemberValue ) 1154 { 1155 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1156 // first we have to check if we could change the property inside the DMS 1157 ::rtl::OString sDocInfoValue = ::rtl::OUStringToOString(sNewValue,RTL_TEXTENCODING_ASCII_US); 1158 WORD nDocInfo = 0; 1159 if(&_rsMemberValue == &m_aProps->m_sTitle) 1160 nDocInfo = ODM_TITLETEXT; 1161 else if(&_rsMemberValue == &m_aProps->m_sAuthor) 1162 nDocInfo = ODM_AUTHOR; 1163 else if(&_rsMemberValue == &m_aProps->m_sSubject) 1164 nDocInfo = ODM_SUBJECT; 1165 else if(&_rsMemberValue == &m_aProps->m_sKeywords) 1166 nDocInfo = ODM_KEYWORDS; 1167 else 1168 bError = sal_True; 1169 1170 if(!bError) 1171 { 1172 ODMSTATUS odm = NODMSetDocInfo( ContentProvider::getHandle(), 1173 const_cast<sal_Char*>(m_aProps->m_sDocumentId.getStr()), 1174 nDocInfo, 1175 const_cast<sal_Char*>(sDocInfoValue.getStr()) 1176 ); 1177 if(odm == ODM_SUCCESS) 1178 { 1179 beans::PropertyChangeEvent aEvent; 1180 aEvent.Source = static_cast< cppu::OWeakObject * >( this ); 1181 aEvent.Further = sal_False; 1182 aEvent.PropertyHandle = -1; 1183 aEvent.PropertyName = _rValue.Name; 1184 aEvent.OldValue = uno::makeAny( _rsMemberValue ); 1185 aEvent.NewValue = uno::makeAny( sNewValue ); 1186 1187 _rChanges.getArray()[ _rnChanged ] = aEvent; 1188 1189 _rsMemberValue = sNewValue; 1190 ++_rnChanged; 1191 } 1192 } 1193 } 1194 else 1195 { 1196 // Old value equals new value. No error! 1197 } 1198 } 1199 else 1200 bError = sal_True; 1201 1202 if(bError) 1203 { 1204 _rRet[ _rnCurrentPos ] <<= beans::IllegalTypeException( 1205 rtl::OUString::createFromAscii( 1206 "Property value has wrong type!" ), 1207 static_cast< cppu::OWeakObject * >( this ) ); 1208 } 1209 } 1210 // ----------------------------------------------------------------------------- 1211 1212