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