1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sfx2.hxx" 30 31 #include "frmload.hxx" 32 #include "objshimp.hxx" 33 #include "sfx2/app.hxx" 34 #include "sfx2/dispatch.hxx" 35 #include "sfx2/docfac.hxx" 36 #include "sfx2/docfile.hxx" 37 #include "sfx2/docfilt.hxx" 38 #include "sfx2/doctempl.hxx" 39 #include "sfx2/fcontnr.hxx" 40 #include "sfx2/frame.hxx" 41 #include "sfx2/request.hxx" 42 #include "sfx2/sfx.hrc" 43 #include "sfx2/sfxsids.hrc" 44 #include "sfx2/sfxuno.hxx" 45 #include "sfx2/viewfrm.hxx" 46 #include "sfx2/viewsh.hxx" 47 #include "sfx2/viewfac.hxx" 48 49 /** === begin UNO includes === **/ 50 #include <com/sun/star/container/XContainerQuery.hpp> 51 #include <com/sun/star/document/XTypeDetection.hpp> 52 #include <com/sun/star/frame/XFrame.hpp> 53 #include <com/sun/star/frame/XLoadable.hpp> 54 #include <com/sun/star/frame/XModel.hpp> 55 #include <com/sun/star/task/XInteractionHandler2.hpp> 56 #include <com/sun/star/document/XViewDataSupplier.hpp> 57 #include <com/sun/star/container/XIndexAccess.hpp> 58 /** === end UNO includes === **/ 59 60 #include <comphelper/interaction.hxx> 61 #include <comphelper/namedvaluecollection.hxx> 62 #include <comphelper/sequenceashashmap.hxx> 63 #include <cppuhelper/exc_hlp.hxx> 64 #include <framework/interaction.hxx> 65 #include <rtl/logfile.hxx> 66 #include <rtl/ustring.h> 67 #include <sot/storinfo.hxx> 68 #include <svtools/ehdl.hxx> 69 #include <svl/eitem.hxx> 70 #include <svl/itemset.hxx> 71 #include <unotools/moduleoptions.hxx> 72 #include <svtools/sfxecode.hxx> 73 #include <svl/stritem.hxx> 74 #include <toolkit/helper/vclunohelper.hxx> 75 #include <tools/diagnose_ex.h> 76 #include <ucbhelper/simpleinteractionrequest.hxx> 77 #include <vos/mutex.hxx> 78 79 /** === begin UNO using === **/ 80 using ::com::sun::star::beans::PropertyValue; 81 using ::com::sun::star::container::XContainerQuery; 82 using ::com::sun::star::container::XEnumeration; 83 using ::com::sun::star::document::XTypeDetection; 84 using ::com::sun::star::frame::XFrame; 85 using ::com::sun::star::frame::XLoadable; 86 using ::com::sun::star::frame::XModel; 87 using ::com::sun::star::lang::XMultiServiceFactory; 88 using ::com::sun::star::task::XInteractionHandler; 89 using ::com::sun::star::task::XInteractionHandler2; 90 using ::com::sun::star::task::XInteractionRequest; 91 using ::com::sun::star::task::XStatusIndicator; 92 using ::com::sun::star::uno::Any; 93 using ::com::sun::star::uno::Exception; 94 using ::com::sun::star::uno::Reference; 95 using ::com::sun::star::uno::RuntimeException; 96 using ::com::sun::star::uno::Sequence; 97 using ::com::sun::star::uno::UNO_QUERY; 98 using ::com::sun::star::uno::UNO_QUERY_THROW; 99 using ::com::sun::star::uno::UNO_SET_THROW; 100 using ::com::sun::star::uno::makeAny; 101 using ::com::sun::star::util::XCloseable; 102 using ::com::sun::star::document::XViewDataSupplier; 103 using ::com::sun::star::container::XIndexAccess; 104 using ::com::sun::star::frame::XController2; 105 using ::com::sun::star::frame::XController; 106 using ::com::sun::star::frame::XModel2; 107 /** === end UNO using === **/ 108 109 SfxFrameLoader_Impl::SfxFrameLoader_Impl( const Reference< XMultiServiceFactory >& _rxFactory ) 110 :m_aContext( _rxFactory ) 111 { 112 } 113 114 SfxFrameLoader_Impl::~SfxFrameLoader_Impl() 115 { 116 } 117 118 // -------------------------------------------------------------------------------------------------------------------- 119 const SfxFilter* SfxFrameLoader_Impl::impl_detectFilterForURL( const ::rtl::OUString& sURL, 120 const ::comphelper::NamedValueCollection& i_rDescriptor, const SfxFilterMatcher& rMatcher ) const 121 { 122 ::rtl::OUString sFilter; 123 try 124 { 125 if ( !sURL.getLength() ) 126 return 0; 127 128 Reference< XTypeDetection > xDetect( 129 m_aContext.createComponent( "com.sun.star.document.TypeDetection" ), 130 UNO_QUERY_THROW); 131 132 ::comphelper::NamedValueCollection aNewArgs; 133 aNewArgs.put( "URL", sURL ); 134 135 if ( i_rDescriptor.has( "InteractionHandler" ) ) 136 aNewArgs.put( "InteractionHandler", i_rDescriptor.get( "InteractionHandler" ) ); 137 if ( i_rDescriptor.has( "StatusIndicator" ) ) 138 aNewArgs.put( "StatusIndicator", i_rDescriptor.get( "StatusIndicator" ) ); 139 140 Sequence< PropertyValue > aQueryArgs( aNewArgs.getPropertyValues() ); 141 ::rtl::OUString sType = xDetect->queryTypeByDescriptor( aQueryArgs, sal_True ); 142 if ( sType.getLength() ) 143 { 144 const SfxFilter* pFilter = rMatcher.GetFilter4EA( sType ); 145 if ( pFilter ) 146 sFilter = pFilter->GetName(); 147 } 148 } 149 catch ( const RuntimeException& ) 150 { 151 throw; 152 } 153 catch( const Exception& ) 154 { 155 DBG_UNHANDLED_EXCEPTION(); 156 sFilter = ::rtl::OUString(); 157 } 158 159 const SfxFilter* pFilter = 0; 160 if (sFilter.getLength()) 161 pFilter = rMatcher.GetFilter4FilterName(sFilter); 162 return pFilter; 163 } 164 165 // -------------------------------------------------------------------------------------------------------------------- 166 const SfxFilter* SfxFrameLoader_Impl::impl_getFilterFromServiceName_nothrow( const ::rtl::OUString& i_rServiceName ) const 167 { 168 try 169 { 170 ::comphelper::NamedValueCollection aQuery; 171 aQuery.put( "DocumentService", i_rServiceName ); 172 173 const Reference< XContainerQuery > xQuery( 174 m_aContext.createComponent( "com.sun.star.document.FilterFactory" ), 175 UNO_QUERY_THROW ); 176 177 const SfxFilterMatcher& rMatcher = SFX_APP()->GetFilterMatcher(); 178 const SfxFilterFlags nMust = SFX_FILTER_IMPORT; 179 const SfxFilterFlags nDont = SFX_FILTER_NOTINSTALLED; 180 181 Reference < XEnumeration > xEnum( xQuery->createSubSetEnumerationByProperties( 182 aQuery.getNamedValues() ), UNO_SET_THROW ); 183 while ( xEnum->hasMoreElements() ) 184 { 185 ::comphelper::NamedValueCollection aType( xEnum->nextElement() ); 186 ::rtl::OUString sFilterName = aType.getOrDefault( "Name", ::rtl::OUString() ); 187 if ( !sFilterName.getLength() ) 188 continue; 189 190 const SfxFilter* pFilter = rMatcher.GetFilter4FilterName( sFilterName ); 191 if ( !pFilter ) 192 continue; 193 194 SfxFilterFlags nFlags = pFilter->GetFilterFlags(); 195 if ( ( ( nFlags & nMust ) == nMust ) 196 && ( ( nFlags & nDont ) == 0 ) 197 ) 198 { 199 return pFilter; 200 } 201 } 202 } 203 catch( const Exception& ) 204 { 205 DBG_UNHANDLED_EXCEPTION(); 206 } 207 return NULL; 208 } 209 210 // -------------------------------------------------------------------------------------------------------------------- 211 ::rtl::OUString SfxFrameLoader_Impl::impl_askForFilter_nothrow( const Reference< XInteractionHandler >& i_rxHandler, 212 const ::rtl::OUString& i_rDocumentURL ) const 213 { 214 ENSURE_OR_THROW( i_rxHandler.is(), "invalid interaction handler" ); 215 216 ::rtl::OUString sFilterName; 217 try 218 { 219 ::framework::RequestFilterSelect aRequest( i_rDocumentURL ); 220 i_rxHandler->handle( aRequest.GetRequest() ); 221 if( !aRequest.isAbort() ) 222 sFilterName = aRequest.getFilter(); 223 } 224 catch( const Exception& ) 225 { 226 DBG_UNHANDLED_EXCEPTION(); 227 } 228 229 return sFilterName; 230 } 231 232 // -------------------------------------------------------------------------------------------------------------------- 233 namespace 234 { 235 sal_Bool lcl_getDispatchResult( const SfxPoolItem* _pResult ) 236 { 237 if ( !_pResult ) 238 return sal_False; 239 240 // default must be set to true, because some return values 241 // cant be checked, but nonetheless indicate "success"! 242 sal_Bool bSuccess = sal_True; 243 244 // On the other side some special slots return a boolean state, 245 // which can be set to FALSE. 246 SfxBoolItem *pItem = PTR_CAST( SfxBoolItem, _pResult ); 247 if ( pItem ) 248 bSuccess = pItem->GetValue(); 249 250 return bSuccess; 251 } 252 } 253 254 // -------------------------------------------------------------------------------------------------------------------- 255 sal_Bool SfxFrameLoader_Impl::impl_createNewDocWithSlotParam( const sal_uInt16 _nSlotID, const Reference< XFrame >& i_rxFrame, 256 const bool i_bHidden ) 257 { 258 SfxRequest aRequest( _nSlotID, SFX_CALLMODE_SYNCHRON, SFX_APP()->GetPool() ); 259 aRequest.AppendItem( SfxUnoFrameItem( SID_FILLFRAME, i_rxFrame ) ); 260 if ( i_bHidden ) 261 aRequest.AppendItem( SfxBoolItem( SID_HIDDEN, sal_True ) ); 262 return lcl_getDispatchResult( SFX_APP()->ExecuteSlot( aRequest ) ); 263 } 264 265 // -------------------------------------------------------------------------------------------------------------------- 266 void SfxFrameLoader_Impl::impl_determineFilter( ::comphelper::NamedValueCollection& io_rDescriptor ) const 267 { 268 const ::rtl::OUString sURL = io_rDescriptor.getOrDefault( "URL", ::rtl::OUString() ); 269 const ::rtl::OUString sTypeName = io_rDescriptor.getOrDefault( "TypeName", ::rtl::OUString() ); 270 const ::rtl::OUString sFilterName = io_rDescriptor.getOrDefault( "FilterName", ::rtl::OUString() ); 271 const ::rtl::OUString sServiceName = io_rDescriptor.getOrDefault( "DocumentService", ::rtl::OUString() ); 272 const Reference< XInteractionHandler > 273 xInteraction = io_rDescriptor.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ); 274 275 const SfxFilterMatcher& rMatcher = SFX_APP()->GetFilterMatcher(); 276 const SfxFilter* pFilter = NULL; 277 278 // get filter by its name directly ... 279 if ( sFilterName.getLength() ) 280 pFilter = rMatcher.GetFilter4FilterName( sFilterName ); 281 282 // or search the preferred filter for the detected type ... 283 if ( !pFilter && sTypeName.getLength() ) 284 pFilter = rMatcher.GetFilter4EA( sTypeName ); 285 286 // or use given document service for detection, too 287 if ( !pFilter && sServiceName.getLength() ) 288 pFilter = impl_getFilterFromServiceName_nothrow( sServiceName ); 289 290 // or use interaction to ask user for right filter. 291 if ( !pFilter && xInteraction.is() && sURL.getLength() ) 292 { 293 ::rtl::OUString sSelectedFilter = impl_askForFilter_nothrow( xInteraction, sURL ); 294 if ( sSelectedFilter.getLength() ) 295 pFilter = rMatcher.GetFilter4FilterName( sSelectedFilter ); 296 } 297 298 if ( pFilter ) 299 { 300 io_rDescriptor.put( "FilterName", ::rtl::OUString( pFilter->GetFilterName() ) ); 301 302 // If detected filter indicates using of an own template format 303 // add property "AsTemplate" to descriptor. But suppress this step 304 // if such property already exists. 305 if ( pFilter->IsOwnTemplateFormat() && !io_rDescriptor.has( "AsTemplate" ) ) 306 io_rDescriptor.put( "AsTemplate", sal_Bool( sal_True ) ); 307 308 // The DocumentService property will finally be used to determine the document type to create, so 309 // override it with the service name as indicated by the found filter. 310 io_rDescriptor.put( "DocumentService", ::rtl::OUString( pFilter->GetServiceName() ) ); 311 } 312 } 313 314 // -------------------------------------------------------------------------------------------------------------------- 315 SfxObjectShellRef SfxFrameLoader_Impl::impl_findObjectShell( const Reference< XModel2 >& i_rxDocument ) const 316 { 317 for ( SfxObjectShell* pDoc = SfxObjectShell::GetFirst( NULL, sal_False ); pDoc; pDoc = SfxObjectShell::GetNext( *pDoc, NULL, sal_False ) ) 318 { 319 if ( i_rxDocument == pDoc->GetModel() ) 320 { 321 return pDoc; 322 } 323 } 324 325 DBG_ERROR( "SfxFrameLoader_Impl::impl_findObjectShell: model is not based on SfxObjectShell - wrong frame loader usage!" ); 326 return NULL; 327 } 328 329 // -------------------------------------------------------------------------------------------------------------------- 330 bool SfxFrameLoader_Impl::impl_determineTemplateDocument( ::comphelper::NamedValueCollection& io_rDescriptor ) const 331 { 332 const ::rtl::OUString sTemplateRegioName = io_rDescriptor.getOrDefault( "TemplateRegionName", ::rtl::OUString() ); 333 const ::rtl::OUString sTemplateName = io_rDescriptor.getOrDefault( "TemplateName", ::rtl::OUString() ); 334 const ::rtl::OUString sServiceName = io_rDescriptor.getOrDefault( "DocumentService", ::rtl::OUString() ); 335 const ::rtl::OUString sURL = io_rDescriptor.getOrDefault( "URL", ::rtl::OUString() ); 336 337 // determine the full URL of the template to use, if any 338 String sTemplateURL; 339 if ( sTemplateRegioName.getLength() && sTemplateName.getLength() ) 340 { 341 SfxDocumentTemplates aTmpFac; 342 aTmpFac.GetFull( sTemplateRegioName, sTemplateName, sTemplateURL ); 343 } 344 else 345 { 346 if ( sServiceName.getLength() ) 347 sTemplateURL = SfxObjectFactory::GetStandardTemplate( sServiceName ); 348 else 349 sTemplateURL = SfxObjectFactory::GetStandardTemplate( SfxObjectShell::GetServiceNameFromFactory( sURL ) ); 350 } 351 352 if ( sTemplateURL.Len() > 0 ) 353 { 354 // detect the filter for the template. Might still be NULL (if the template is broken, or does not 355 // exist, or some such), but this is handled by our caller the same way as if no template/URL was present. 356 const SfxFilter* pTemplateFilter = impl_detectFilterForURL( sTemplateURL, io_rDescriptor, SFX_APP()->GetFilterMatcher() ); 357 if ( pTemplateFilter ) 358 { 359 // load the template document, but, well, "as template" 360 io_rDescriptor.put( "FilterName", ::rtl::OUString( pTemplateFilter->GetName() ) ); 361 io_rDescriptor.put( "FileName", ::rtl::OUString( sTemplateURL ) ); 362 io_rDescriptor.put( "AsTemplate", sal_True ); 363 364 // #i21583# 365 // the DocumentService property will finally be used to create the document. Thus, override any possibly 366 // present value with the document service of the template. 367 io_rDescriptor.put( "DocumentService", ::rtl::OUString( pTemplateFilter->GetServiceName() ) ); 368 return true; 369 } 370 } 371 return false; 372 } 373 374 // -------------------------------------------------------------------------------------------------------------------- 375 sal_uInt16 SfxFrameLoader_Impl::impl_findSlotParam( const ::rtl::OUString& i_rFactoryURL ) const 376 { 377 ::rtl::OUString sSlotParam; 378 const sal_Int32 nParamPos = i_rFactoryURL.indexOf( '?' ); 379 if ( nParamPos >= 0 ) 380 { 381 // currently only the "slot" parameter is supported 382 const sal_Int32 nSlotPos = i_rFactoryURL.indexOfAsciiL( RTL_CONSTASCII_STRINGPARAM( "slot=" ), nParamPos ); 383 if ( nSlotPos > 0 ) 384 sSlotParam = i_rFactoryURL.copy( nSlotPos + 5 ); 385 } 386 387 if ( sSlotParam.getLength() ) 388 return sal_uInt16( sSlotParam.toInt32() ); 389 390 return 0; 391 } 392 393 // -------------------------------------------------------------------------------------------------------------------- 394 void SfxFrameLoader_Impl::impl_handleCaughtError_nothrow( const Any& i_rCaughtError, const ::comphelper::NamedValueCollection& i_rDescriptor ) const 395 { 396 try 397 { 398 const Reference< XInteractionHandler > xInteraction = 399 i_rDescriptor.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ); 400 if ( !xInteraction.is() ) 401 return; 402 ::rtl::Reference< ::comphelper::OInteractionRequest > pRequest( new ::comphelper::OInteractionRequest( i_rCaughtError ) ); 403 ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove( new ::comphelper::OInteractionApprove ); 404 pRequest->addContinuation( pApprove.get() ); 405 406 const Reference< XInteractionHandler2 > xHandler( xInteraction, UNO_QUERY ); 407 #if OSL_DEBUG_LEVEL > 0 408 const sal_Bool bHandled = 409 #endif 410 xHandler.is() && xHandler->handleInteractionRequest( pRequest.get() ); 411 412 #if OSL_DEBUG_LEVEL > 0 413 if ( !bHandled ) 414 // the interaction handler couldn't deal with this error 415 // => report it as assertion, at least (done in the DBG_UNHANDLED_EXCEPTION below) 416 ::cppu::throwException( i_rCaughtError ); 417 #endif 418 } 419 catch( const Exception& ) 420 { 421 DBG_UNHANDLED_EXCEPTION(); 422 } 423 } 424 425 // -------------------------------------------------------------------------------------------------------------------- 426 void SfxFrameLoader_Impl::impl_removeLoaderArguments( ::comphelper::NamedValueCollection& io_rDescriptor ) 427 { 428 // remove the arguments which are for the loader only, and not for a call to attachResource 429 io_rDescriptor.remove( "StatusIndicator" ); 430 io_rDescriptor.remove( "Model" ); 431 } 432 433 // -------------------------------------------------------------------------------------------------------------------- 434 ::comphelper::NamedValueCollection SfxFrameLoader_Impl::impl_extractViewCreationArgs( ::comphelper::NamedValueCollection& io_rDescriptor ) 435 { 436 const sal_Char* pKnownViewArgs[] = { 437 "JumpMark" 438 }; 439 440 ::comphelper::NamedValueCollection aViewArgs; 441 for ( size_t i=0; i < sizeof( pKnownViewArgs ) / sizeof( pKnownViewArgs[0] ); ++i ) 442 { 443 if ( io_rDescriptor.has( pKnownViewArgs[i] ) ) 444 { 445 aViewArgs.put( pKnownViewArgs[i], io_rDescriptor.get( pKnownViewArgs[i] ) ); 446 io_rDescriptor.remove( pKnownViewArgs[i] ); 447 } 448 } 449 return aViewArgs; 450 } 451 452 // -------------------------------------------------------------------------------------------------------------------- 453 sal_Int16 SfxFrameLoader_Impl::impl_determineEffectiveViewId_nothrow( const SfxObjectShell& i_rDocument, const ::comphelper::NamedValueCollection& i_rDescriptor ) 454 { 455 sal_Int16 nViewId = i_rDescriptor.getOrDefault( "ViewId", sal_Int16( 0 ) ); 456 try 457 { 458 if ( nViewId == 0 ) do 459 { 460 Reference< XViewDataSupplier > xViewDataSupplier( i_rDocument.GetModel(), UNO_QUERY ); 461 Reference< XIndexAccess > xViewData; 462 if ( xViewDataSupplier.is() ) 463 xViewData.set( xViewDataSupplier->getViewData() ); 464 465 if ( !xViewData.is() || ( xViewData->getCount() == 0 ) ) 466 // no view data stored together with the model 467 break; 468 469 // obtain the ViewID from the view data 470 Sequence< PropertyValue > aViewData; 471 if ( !( xViewData->getByIndex( 0 ) >>= aViewData ) ) 472 break; 473 474 ::comphelper::NamedValueCollection aNamedViewData( aViewData ); 475 ::rtl::OUString sViewId = aNamedViewData.getOrDefault( "ViewId", ::rtl::OUString() ); 476 if ( !sViewId.getLength() ) 477 break; 478 479 // somewhat weird convention here ... in the view data, the ViewId is a string, effectively describing 480 // a view name. In the document load descriptor, the ViewId is in fact the numeric ID. 481 482 SfxViewFactory* pViewFactory = i_rDocument.GetFactory().GetViewFactoryByViewName( sViewId ); 483 if ( pViewFactory ) 484 nViewId = sal_Int16( pViewFactory->GetOrdinal() ); 485 } 486 while ( false ); 487 } 488 catch( const Exception& ) 489 { 490 DBG_UNHANDLED_EXCEPTION(); 491 } 492 493 if ( nViewId == 0 ) 494 nViewId = i_rDocument.GetFactory().GetViewFactory( 0 ).GetOrdinal(); 495 return nViewId; 496 } 497 498 // -------------------------------------------------------------------------------------------------------------------- 499 Reference< XController2 > SfxFrameLoader_Impl::impl_createDocumentView( const Reference< XModel2 >& i_rModel, 500 const Reference< XFrame >& i_rFrame, const ::comphelper::NamedValueCollection& i_rViewFactoryArgs, 501 const ::rtl::OUString& i_rViewName ) 502 { 503 // let the model create a new controller 504 const Reference< XController2 > xController( i_rModel->createViewController( 505 i_rViewName, 506 i_rViewFactoryArgs.getPropertyValues(), 507 i_rFrame 508 ), UNO_SET_THROW ); 509 510 // introduce model/view/controller to each other 511 xController->attachModel( i_rModel.get() ); 512 i_rModel->connectController( xController.get() ); 513 i_rFrame->setComponent( xController->getComponentWindow(), xController.get() ); 514 xController->attachFrame( i_rFrame ); 515 i_rModel->setCurrentController( xController.get() ); 516 517 return xController; 518 } 519 520 // -------------------------------------------------------------------------------------------------------------------- 521 sal_Bool SAL_CALL SfxFrameLoader_Impl::load( const Sequence< PropertyValue >& rArgs, 522 const Reference< XFrame >& _rTargetFrame ) 523 throw( RuntimeException ) 524 { 525 ENSURE_OR_THROW( _rTargetFrame.is(), "illegal NULL frame" ); 526 527 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 528 529 RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mb93783) ::SfxFrameLoader::load" ); 530 531 ::comphelper::NamedValueCollection aDescriptor( rArgs ); 532 533 // ensure the descriptor contains a referrer 534 if ( !aDescriptor.has( "Referer" ) ) 535 aDescriptor.put( "Referer", ::rtl::OUString() ); 536 537 // TODO: is this needed? finally, when loading is successfull, then there should be no need for this item, 538 // as the document can always obtain its frame. In particular, there might be situations where this frame 539 // is accessed, but already disposed: Imagine the user loading a document, opening a second view on it, and 540 // then closing the first view/frame. 541 aDescriptor.put( "Frame", _rTargetFrame ); 542 543 // did the caller already pass a model? 544 Reference< XModel2 > xModel = aDescriptor.getOrDefault( "Model", Reference< XModel2 >() ); 545 const bool bExternalModel = xModel.is(); 546 547 // check for factory URLs to create a new doc, instead of loading one 548 const ::rtl::OUString sURL = aDescriptor.getOrDefault( "URL", ::rtl::OUString() ); 549 const bool bIsFactoryURL = ( sURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "private:factory/" ) ) == 0 ); 550 bool bInitNewModel = bIsFactoryURL; 551 if ( bIsFactoryURL && !bExternalModel ) 552 { 553 const ::rtl::OUString sFactory = sURL.copy( sizeof( "private:factory/" ) -1 ); 554 // special handling for some weird factory URLs a la private:factory/swriter?slot=21053 555 const sal_uInt16 nSlotParam = impl_findSlotParam( sFactory ); 556 if ( nSlotParam != 0 ) 557 { 558 return impl_createNewDocWithSlotParam( nSlotParam, _rTargetFrame, aDescriptor.getOrDefault( "Hidden", false ) ); 559 } 560 561 const bool bDescribesValidTemplate = impl_determineTemplateDocument( aDescriptor ); 562 if ( bDescribesValidTemplate ) 563 { 564 // if the media descriptor allowed us to determine a template document to create the new document 565 // from, then do not init a new document model from scratch (below), but instead load the 566 // template document 567 bInitNewModel = false; 568 } 569 else 570 { 571 const ::rtl::OUString sServiceName = SfxObjectShell::GetServiceNameFromFactory( sFactory ); 572 aDescriptor.put( "DocumentService", sServiceName ); 573 } 574 } 575 else 576 { 577 // compatibility 578 aDescriptor.put( "FileName", aDescriptor.get( "URL" ) ); 579 } 580 581 sal_Bool bLoadSuccess = sal_False; 582 try 583 { 584 // extract view releant arguments from the loader args 585 ::comphelper::NamedValueCollection aViewCreationArgs( impl_extractViewCreationArgs( aDescriptor ) ); 586 587 // no model passed from outside? => create one from scratch 588 if ( !xModel.is() ) 589 { 590 // beforehand, determine the filter to use, and update the descriptor with its information 591 if ( !bInitNewModel ) 592 { 593 impl_determineFilter( aDescriptor ); 594 } 595 596 // create the new doc 597 const ::rtl::OUString sServiceName = aDescriptor.getOrDefault( "DocumentService", ::rtl::OUString() ); 598 xModel.set( m_aContext.createComponent( sServiceName ), UNO_QUERY_THROW ); 599 600 // load resp. init it 601 const Reference< XLoadable > xLoadable( xModel, UNO_QUERY_THROW ); 602 if ( bInitNewModel ) 603 { 604 xLoadable->initNew(); 605 606 impl_removeLoaderArguments( aDescriptor ); 607 xModel->attachResource( ::rtl::OUString(), aDescriptor.getPropertyValues() ); 608 } 609 else 610 { 611 xLoadable->load( aDescriptor.getPropertyValues() ); 612 } 613 } 614 else 615 { 616 // tell the doc its (current) load args. 617 impl_removeLoaderArguments( aDescriptor ); 618 xModel->attachResource( xModel->getURL(), aDescriptor.getPropertyValues() ); 619 } 620 621 // get the SfxObjectShell (still needed at the moment) 622 // SfxObjectShellRef is used here ( instead of ...Lock ) since the model is closed below if necessary 623 // SfxObjectShellLock would be even dangerous here, since the lifetime control should be done outside in case of success 624 const SfxObjectShellRef xDoc = impl_findObjectShell( xModel ); 625 ENSURE_OR_THROW( xDoc.Is(), "no SfxObjectShell for the given model" ); 626 627 // ensure the ID of the to-be-created view is in the descriptor, if possible 628 const sal_Int16 nViewId = impl_determineEffectiveViewId_nothrow( *xDoc, aDescriptor ); 629 const sal_Int16 nViewNo = xDoc->GetFactory().GetViewNo_Impl( nViewId, 0 ); 630 const ::rtl::OUString sViewName( xDoc->GetFactory().GetViewFactory( nViewNo ).GetAPIViewName() ); 631 632 // plug the document into the frame 633 impl_createDocumentView( xModel, _rTargetFrame, aViewCreationArgs, sViewName ); 634 bLoadSuccess = sal_True; 635 } 636 catch ( Exception& ) 637 { 638 const Any aError( ::cppu::getCaughtException() ); 639 if ( !aDescriptor.getOrDefault( "Silent", sal_False ) ) 640 impl_handleCaughtError_nothrow( aError, aDescriptor ); 641 } 642 643 // if loading was not successful, close the document 644 if ( !bLoadSuccess && !bExternalModel ) 645 { 646 try 647 { 648 const Reference< XCloseable > xCloseable( xModel, UNO_QUERY_THROW ); 649 xCloseable->close( sal_True ); 650 } 651 catch ( Exception& ) 652 { 653 DBG_UNHANDLED_EXCEPTION(); 654 } 655 } 656 657 return bLoadSuccess; 658 } 659 660 void SfxFrameLoader_Impl::cancel() throw( RuntimeException ) 661 { 662 } 663 664 SFX_IMPL_SINGLEFACTORY( SfxFrameLoader_Impl ) 665 666 /* XServiceInfo */ 667 UNOOUSTRING SAL_CALL SfxFrameLoader_Impl::getImplementationName() throw( RuntimeException ) 668 { 669 return impl_getStaticImplementationName(); 670 } 671 \ 672 /* XServiceInfo */ 673 sal_Bool SAL_CALL SfxFrameLoader_Impl::supportsService( const UNOOUSTRING& sServiceName ) throw( RuntimeException ) 674 { 675 UNOSEQUENCE< UNOOUSTRING > seqServiceNames = getSupportedServiceNames(); 676 const UNOOUSTRING* pArray = seqServiceNames.getConstArray(); 677 for ( sal_Int32 nCounter=0; nCounter<seqServiceNames.getLength(); nCounter++ ) 678 { 679 if ( pArray[nCounter] == sServiceName ) 680 { 681 return sal_True ; 682 } 683 } 684 return sal_False ; 685 } 686 687 /* XServiceInfo */ 688 UNOSEQUENCE< UNOOUSTRING > SAL_CALL SfxFrameLoader_Impl::getSupportedServiceNames() throw( RuntimeException ) 689 { 690 return impl_getStaticSupportedServiceNames(); 691 } 692 693 /* Helper for XServiceInfo */ 694 UNOSEQUENCE< UNOOUSTRING > SfxFrameLoader_Impl::impl_getStaticSupportedServiceNames() 695 { 696 UNOMUTEXGUARD aGuard( UNOMUTEX::getGlobalMutex() ); 697 UNOSEQUENCE< UNOOUSTRING > seqServiceNames( 1 ); 698 seqServiceNames.getArray() [0] = UNOOUSTRING::createFromAscii( "com.sun.star.frame.SynchronousFrameLoader" ); 699 return seqServiceNames ; 700 } 701 702 /* Helper for XServiceInfo */ 703 UNOOUSTRING SfxFrameLoader_Impl::impl_getStaticImplementationName() 704 { 705 return UNOOUSTRING::createFromAscii( "com.sun.star.comp.office.FrameLoader" ); 706 } 707 708 /* Helper for registry */ 709 UNOREFERENCE< UNOXINTERFACE > SAL_CALL SfxFrameLoader_Impl::impl_createInstance( const UNOREFERENCE< UNOXMULTISERVICEFACTORY >& xServiceManager ) throw( UNOEXCEPTION ) 710 { 711 return UNOREFERENCE< UNOXINTERFACE >( *new SfxFrameLoader_Impl( xServiceManager ) ); 712 } 713 714