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_dbmm.hxx"
26 
27 #include "dbmm_global.hrc"
28 #include "dbmm_module.hxx"
29 #include "docinteraction.hxx"
30 #include "macromigration.hrc"
31 #include "macromigrationdialog.hxx"
32 #include "macromigrationpages.hxx"
33 #include "migrationengine.hxx"
34 #include "migrationerror.hxx"
35 #include "migrationlog.hxx"
36 
37 /** === begin UNO includes === **/
38 #include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
39 #include <com/sun/star/frame/XModel2.hpp>
40 #include <com/sun/star/frame/XStorable.hpp>
41 #include <com/sun/star/util/XCloseable.hpp>
42 #include <com/sun/star/frame/XComponentLoader.hpp>
43 #include <com/sun/star/util/XModifiable.hpp>
44 #include <com/sun/star/ucb/XContent.hpp>
45 #include <com/sun/star/ucb/XContentProvider.hpp>
46 /** === end UNO includes === **/
47 
48 #include <comphelper/namedvaluecollection.hxx>
49 #include <cppuhelper/exc_hlp.hxx>
50 #include <cppuhelper/implbase1.hxx>
51 #include <rtl/ref.hxx>
52 #include <svl/filenotation.hxx>
53 #include <tools/diagnose_ex.h>
54 #include <ucbhelper/content.hxx>
55 #include <ucbhelper/contentbroker.hxx>
56 #include <vcl/msgbox.hxx>
57 
58 #include <list>
59 
60 //........................................................................
61 namespace dbmm
62 {
63 //........................................................................
64 
65 #define STATE_CLOSE_SUB_DOCS    0
66 #define STATE_BACKUP_DBDOC      1
67 #define STATE_MIGRATE           2
68 #define STATE_SUMMARY           3
69 
70 #define PATH_DEFAULT            1
71 
72 	/** === begin UNO using === **/
73 	using ::com::sun::star::uno::Reference;
74 	using ::com::sun::star::uno::XInterface;
75 	using ::com::sun::star::uno::UNO_QUERY;
76 	using ::com::sun::star::uno::UNO_QUERY_THROW;
77 	using ::com::sun::star::uno::UNO_SET_THROW;
78 	using ::com::sun::star::uno::Exception;
79 	using ::com::sun::star::uno::RuntimeException;
80 	using ::com::sun::star::uno::Any;
81 	using ::com::sun::star::uno::makeAny;
82     using ::com::sun::star::sdb::application::XDatabaseDocumentUI;
83     using ::com::sun::star::sdb::XOfficeDatabaseDocument;
84     using ::com::sun::star::frame::XModel2;
85     using ::com::sun::star::frame::XController;
86     using ::com::sun::star::frame::XController2;
87     using ::com::sun::star::container::XEnumeration;
88     using ::com::sun::star::frame::XStorable;
89     using ::com::sun::star::uno::Sequence;
90     using ::com::sun::star::beans::PropertyValue;
91     using ::com::sun::star::frame::XFrame;
92     using ::com::sun::star::awt::XWindow;
93     using ::com::sun::star::util::XCloseable;
94     using ::com::sun::star::util::XCloseListener;
95     using ::com::sun::star::util::CloseVetoException;
96     using ::com::sun::star::lang::EventObject;
97     using ::com::sun::star::frame::XComponentLoader;
98     using ::com::sun::star::util::XModifiable;
99     using ::com::sun::star::ucb::XCommandEnvironment;
100     using ::com::sun::star::ucb::XContent;
101     using ::com::sun::star::ucb::XContentIdentifier;
102     using ::com::sun::star::ucb::XContentProvider;
103 	/** === end UNO using === **/
104 
105 	//====================================================================
106 	//= helper
107 	//====================================================================
108     //--------------------------------------------------------------------
lcl_getControllers_throw(const Reference<XModel2> & _rxDocument,::std::list<Reference<XController2>> & _out_rControllers)109     static void lcl_getControllers_throw( const Reference< XModel2 >& _rxDocument,
110         ::std::list< Reference< XController2 > >& _out_rControllers )
111     {
112         _out_rControllers.clear();
113         Reference< XEnumeration > xControllerEnum( _rxDocument->getControllers(), UNO_SET_THROW );
114         while ( xControllerEnum->hasMoreElements() )
115             _out_rControllers.push_back( Reference< XController2 >( xControllerEnum->nextElement(), UNO_QUERY_THROW ) );
116     }
117 
118 	//====================================================================
119 	//= MacroMigrationDialog_Data
120 	//====================================================================
121     struct MacroMigrationDialog_Data
122     {
123         ::comphelper::ComponentContext          aContext;
124         MigrationLog                            aLogger;
125         Reference< XOfficeDatabaseDocument >    xDocument;
126         Reference< XModel2 >                    xDocumentModel;
127         ::rtl::OUString                         sSuccessfulBackupLocation;
128         bool                                    bMigrationIsRunning;
129         bool                                    bMigrationFailure;
130         bool                                    bMigrationSuccess;
131 
MacroMigrationDialog_Datadbmm::MacroMigrationDialog_Data132         MacroMigrationDialog_Data(
133                 const ::comphelper::ComponentContext& _rContext,
134                 const Reference< XOfficeDatabaseDocument >& _rxDocument )
135             :aContext( _rContext )
136             ,aLogger()
137             ,xDocument( _rxDocument )
138             ,xDocumentModel( _rxDocument, UNO_QUERY )
139             ,bMigrationIsRunning( false )
140             ,bMigrationFailure( false )
141             ,bMigrationSuccess( false )
142         {
143         }
144     };
145 
146 	//====================================================================
147 	//= MacroMigrationDialog
148 	//====================================================================
149 	//--------------------------------------------------------------------
MacroMigrationDialog(Window * _pParent,const::comphelper::ComponentContext & _rContext,const Reference<XOfficeDatabaseDocument> & _rxDocument)150     MacroMigrationDialog::MacroMigrationDialog( Window* _pParent, const ::comphelper::ComponentContext& _rContext,
151         const Reference< XOfficeDatabaseDocument >& _rxDocument )
152         :MacroMigrationDialog_Base( _pParent, MacroMigrationResId( DLG_MACRO_MIGRATION ) )
153         ,m_pData( new MacroMigrationDialog_Data( _rContext, _rxDocument ) )
154     {
155         String sTitlePrepare( MacroMigrationResId( STR_STATE_CLOSE_SUB_DOCS ) );
156         String sTitleStoreAs( MacroMigrationResId( STR_STATE_BACKUP_DBDOC ) );
157         String sTitleMigrate( MacroMigrationResId( STR_STATE_MIGRATE ) );
158         String sTitleSummary( MacroMigrationResId( STR_STATE_SUMMARY ) );
159         FreeResource();
160 
161         describeState( STATE_CLOSE_SUB_DOCS,    sTitlePrepare, &PreparationPage::Create   );
162         describeState( STATE_BACKUP_DBDOC,      sTitleStoreAs, &SaveDBDocPage::Create     );
163         describeState( STATE_MIGRATE,           sTitleMigrate, &ProgressPage::Create      );
164         describeState( STATE_SUMMARY,           sTitleSummary, &ResultPage::Create        );
165 
166         declarePath( PATH_DEFAULT, STATE_CLOSE_SUB_DOCS, STATE_BACKUP_DBDOC, STATE_MIGRATE, STATE_SUMMARY, WZS_INVALID_STATE );
167 
168         SetPageSizePixel( LogicToPixel( ::Size( TAB_PAGE_WIDTH, TAB_PAGE_HEIGHT ), MAP_APPFONT ) );
169         ShowButtonFixedLine( true );
170         SetRoadmapInteractive( true );
171         enableAutomaticNextButtonState();
172         defaultButton( WZB_NEXT );
173         enableButtons( WZB_FINISH, true );
174         ActivatePage();
175 
176         OSL_PRECOND( m_pData->xDocumentModel.is(), "MacroMigrationDialog::MacroMigrationDialog: illegal document!" );
177     }
178 
179 	//--------------------------------------------------------------------
~MacroMigrationDialog()180     MacroMigrationDialog::~MacroMigrationDialog()
181     {
182     }
183 
184 	//--------------------------------------------------------------------
getComponentContext() const185     const ::comphelper::ComponentContext& MacroMigrationDialog::getComponentContext() const
186     {
187         return m_pData->aContext;
188     }
189 
190 	//--------------------------------------------------------------------
getDocument() const191     const Reference< XOfficeDatabaseDocument >& MacroMigrationDialog::getDocument() const
192     {
193         return m_pData->xDocument;
194     }
195 
196 	//--------------------------------------------------------------------
Execute()197     short MacroMigrationDialog::Execute()
198     {
199         short nResult = MacroMigrationDialog_Base::Execute();
200         if ( !m_pData->bMigrationFailure && !m_pData->bMigrationSuccess )
201             // migration did not even start
202             return nResult;
203 
204         OSL_ENSURE( !m_pData->bMigrationFailure || !m_pData->bMigrationSuccess,
205             "MacroMigrationDialog::Execute: success *and* failure at the same time?!" );
206         impl_reloadDocument_nothrow( m_pData->bMigrationSuccess );
207 
208         return nResult;
209     }
210 
211 	//--------------------------------------------------------------------
Close()212     sal_Bool MacroMigrationDialog::Close()
213     {
214         if ( m_pData->bMigrationIsRunning )
215             return sal_False;
216         return MacroMigrationDialog_Base::Close();
217     }
218 
219 	//--------------------------------------------------------------------
enterState(WizardState _nState)220     void MacroMigrationDialog::enterState( WizardState _nState )
221     {
222         MacroMigrationDialog_Base::enterState( _nState );
223 
224         switch ( _nState )
225         {
226         case STATE_CLOSE_SUB_DOCS:
227             enableButtons( WZB_FINISH, false );
228             enableState( STATE_MIGRATE, false );
229             enableState( STATE_SUMMARY, false );
230             break;
231 
232         case STATE_BACKUP_DBDOC:
233             enableState( STATE_MIGRATE, true );
234             // Note that the state is automatically disabled if the current page
235             // (SaveDBDocPage) returns false in its canAdvance, not caring that
236             // we enabled it here.
237             break;
238 
239         case STATE_MIGRATE:
240         {
241             // disable everything. The process we will start here cannot be cancelled, the user
242             // needs to wait 'til it's finished.
243             enableState( STATE_CLOSE_SUB_DOCS, false );
244             enableState( STATE_BACKUP_DBDOC, false );
245             enableState( STATE_SUMMARY, false );
246 
247             enableButtons( WZB_FINISH | WZB_CANCEL | WZB_PREVIOUS | WZB_NEXT, false );
248 
249             // start the migration asynchronously
250             PostUserEvent( LINK( this, MacroMigrationDialog, OnStartMigration ) );
251         }
252         break;
253 
254         case STATE_SUMMARY:
255             // disable the previous step - we can't return to the actual migration, it already happened (or failed)
256             enableState( STATE_MIGRATE, false );
257             updateTravelUI();
258 
259             // display the results
260             dynamic_cast< ResultPage& >( *GetPage( STATE_SUMMARY ) ).displayMigrationLog(
261                 m_pData->bMigrationSuccess, m_pData->aLogger.getCompleteLog() );
262 
263             enableButtons( WZB_FINISH, m_pData->bMigrationSuccess );
264             enableButtons( WZB_CANCEL, m_pData->bMigrationFailure );
265             defaultButton( m_pData->bMigrationSuccess ? WZB_FINISH : WZB_CANCEL );
266             break;
267 
268         default:
269             OSL_ENSURE( false, "MacroMigrationDialog::enterState: unhandled state!" );
270         }
271     }
272 
273 	//--------------------------------------------------------------------
prepareLeaveCurrentState(CommitPageReason _eReason)274     sal_Bool MacroMigrationDialog::prepareLeaveCurrentState( CommitPageReason _eReason )
275     {
276         if ( !MacroMigrationDialog_Base::prepareLeaveCurrentState( _eReason ) )
277             return sal_False;
278 
279         switch ( getCurrentState() )
280         {
281         case STATE_CLOSE_SUB_DOCS:
282             if ( !impl_closeSubDocs_nothrow() )
283                 return sal_False;
284             break;
285         case STATE_BACKUP_DBDOC:
286             if ( !impl_backupDocument_nothrow() )
287                 return sal_False;
288             break;
289         case STATE_MIGRATE:
290             break;
291         case STATE_SUMMARY:
292             break;
293         default:
294             OSL_ENSURE( false, "MacroMigrationDialog::prepareLeaveCurrentState: unhandled state!" );
295         }
296 
297         return sal_True;
298     }
299 
300 	//--------------------------------------------------------------------
leaveState(WizardState _nState)301     sal_Bool MacroMigrationDialog::leaveState( WizardState _nState )
302     {
303         return MacroMigrationDialog_Base::leaveState( _nState );
304     }
305 
306 	//--------------------------------------------------------------------
determineNextState(WizardState _nCurrentState) const307     MacroMigrationDialog::WizardState MacroMigrationDialog::determineNextState( WizardState _nCurrentState ) const
308     {
309         return MacroMigrationDialog_Base::determineNextState( _nCurrentState );
310     }
311 
312 	//--------------------------------------------------------------------
onFinish()313     sal_Bool MacroMigrationDialog::onFinish()
314     {
315         return MacroMigrationDialog_Base::onFinish();
316     }
317 
318 	//--------------------------------------------------------------------
319     IMPL_LINK( MacroMigrationDialog, OnStartMigration, void*, /*_pNotInterestedIn*/ )
320     {
321         // prevent closing
322         m_pData->bMigrationIsRunning = true;
323 
324         // initialize migration engine and progress
325         ProgressPage& rProgressPage( dynamic_cast< ProgressPage& >( *GetPage( STATE_MIGRATE ) ) );
326         MigrationEngine aEngine( m_pData->aContext, m_pData->xDocument, rProgressPage, m_pData->aLogger );
327         rProgressPage.setDocumentCounts( aEngine.getFormCount(), aEngine.getReportCount() );
328 
329         // do the migration
330         m_pData->bMigrationSuccess = aEngine.migrateAll();
331         m_pData->bMigrationFailure = !m_pData->bMigrationSuccess;
332 
333         // re-enable the UI
334         enableButtons( WZB_FINISH | WZB_NEXT, true );
335         enableState( STATE_SUMMARY, true );
336         updateTravelUI();
337 
338         m_pData->bMigrationIsRunning = false;
339 
340         if ( m_pData->bMigrationSuccess )
341         {
342             rProgressPage.onFinishedSuccessfully();
343         }
344         else
345         {   // if there was an error, show the summary automatically
346             travelNext();
347         }
348 
349         // outta here
350         return 0L;
351     }
352 
353 	//--------------------------------------------------------------------
impl_showCloseDocsError(bool _bShow)354     void MacroMigrationDialog::impl_showCloseDocsError( bool _bShow )
355     {
356         PreparationPage* pPreparationPage = dynamic_cast< PreparationPage* >( GetPage( STATE_CLOSE_SUB_DOCS ) );
357         OSL_ENSURE( pPreparationPage, "MacroMigrationDialog::impl_showCloseDocsError: did not find the page!" );
358         if ( pPreparationPage )
359             pPreparationPage->showCloseDocsError( _bShow );
360     }
361 
362 	//--------------------------------------------------------------------
impl_closeSubDocs_nothrow()363     bool MacroMigrationDialog::impl_closeSubDocs_nothrow()
364     {
365         OSL_PRECOND( m_pData->xDocument.is(), "MacroMigrationDialog::impl_closeSubDocs_nothrow: no document!" );
366         if ( !m_pData->xDocument.is() )
367             return false;
368 
369         impl_showCloseDocsError( false );
370 
371         bool bSuccess = true;
372         try
373         {
374             // collect all controllers of our document
375             ::std::list< Reference< XController2 > > aControllers;
376             lcl_getControllers_throw( m_pData->xDocumentModel, aControllers );
377 
378             // close all sub documents of all controllers
379             for (   ::std::list< Reference< XController2 > >::const_iterator pos = aControllers.begin();
380                     pos != aControllers.end() && bSuccess;
381                     ++pos
382                 )
383             {
384                 Reference< XDatabaseDocumentUI > xController( *pos, UNO_QUERY );
385                 OSL_ENSURE( xController.is(), "MacroMigrationDialog::impl_closeSubDocs_nothrow: unexpected: controller is missing an important interface!" );
386                     // at the moment, only one implementation for a DBDoc's controller exists, which should
387                     // support this interface
388                 if ( !xController.is() )
389                     continue;
390 
391                 bSuccess = xController->closeSubComponents();
392             }
393         }
394         catch( const Exception& )
395         {
396         	DBG_UNHANDLED_EXCEPTION();
397             bSuccess = false;
398         }
399 
400         impl_showCloseDocsError( !bSuccess );
401         return bSuccess;
402     }
403 
404 	//--------------------------------------------------------------------
405     namespace
406     {
lcl_equalURLs_nothrow(const::rtl::OUString & _lhs,const::rtl::OUString _rhs)407         bool    lcl_equalURLs_nothrow( const ::rtl::OUString& _lhs, const ::rtl::OUString _rhs )
408         {
409             // the cheap situation: the URLs are equal
410             if ( _lhs == _rhs )
411                 return true;
412 
413             bool bEqual = true;
414             try
415             {
416 				::ucbhelper::Content aContentLHS = ::ucbhelper::Content( _lhs, Reference< XCommandEnvironment >() );
417 				::ucbhelper::Content aContentRHS = ::ucbhelper::Content( _rhs, Reference< XCommandEnvironment >() );
418 				Reference< XContent > xContentLHS( aContentLHS.get(), UNO_SET_THROW );
419 				Reference< XContent > xContentRHS( aContentRHS.get(), UNO_SET_THROW );
420 				Reference< XContentIdentifier > xID1( xContentLHS->getIdentifier(), UNO_SET_THROW );
421 				Reference< XContentIdentifier > xID2( xContentRHS->getIdentifier(), UNO_SET_THROW );
422 
423                 ::ucbhelper::ContentBroker* pBroker = ::ucbhelper::ContentBroker::get();
424                 Reference< XContentProvider > xProvider(
425                     pBroker ? pBroker->getContentProviderInterface() : Reference< XContentProvider >(), UNO_SET_THROW );
426 
427                 bEqual = ( 0 == xProvider->compareContentIds( xID1, xID2 ) );
428             }
429             catch( const Exception& )
430             {
431             	DBG_UNHANDLED_EXCEPTION();
432             }
433             return bEqual;
434         }
435     }
436 
437 	//--------------------------------------------------------------------
impl_backupDocument_nothrow() const438     bool MacroMigrationDialog::impl_backupDocument_nothrow() const
439     {
440         if ( !m_pData->xDocumentModel.is() )
441             // should never happen, but has been reported as assertion before
442             return false;
443 
444         SaveDBDocPage& rBackupPage = dynamic_cast< SaveDBDocPage& >( *GetPage( STATE_BACKUP_DBDOC ) );
445         ::rtl::OUString sBackupLocation( rBackupPage.getBackupLocation() );
446 
447         Any aError;
448         try
449         {
450             // check that the backup location isn't the same as the document itself
451             if ( lcl_equalURLs_nothrow( sBackupLocation, m_pData->xDocumentModel->getURL() ) )
452             {
453                 ErrorBox aErrorBox( const_cast< MacroMigrationDialog* >( this ), MacroMigrationResId( ERR_INVALID_BACKUP_LOCATION ) );
454                 aErrorBox.Execute();
455                 rBackupPage.grabLocationFocus();
456                 return false;
457             }
458 
459             // store to the backup location
460             const Reference< XStorable > xDocument( getDocument(), UNO_QUERY_THROW );
461             xDocument->storeToURL( sBackupLocation, Sequence< PropertyValue >() );
462             m_pData->sSuccessfulBackupLocation = sBackupLocation;
463         }
464         catch( const Exception& )
465         {
466             aError = ::cppu::getCaughtException();
467         }
468         if ( !aError.hasValue() )
469         {
470             ::svt::OFileNotation aFileNotation( sBackupLocation );
471             m_pData->aLogger.backedUpDocument( aFileNotation.get( ::svt::OFileNotation::N_SYSTEM ) );
472             return true;
473         }
474 
475         // display the error to the user
476         InteractionHandler aHandler( m_pData->aContext, m_pData->xDocumentModel.get() );
477         aHandler.reportError( aError );
478 
479         m_pData->aLogger.logFailure( MigrationError(
480             ERR_DOCUMENT_BACKUP_FAILED,
481             sBackupLocation,
482             aError
483         ) );
484 
485         return false;
486     }
487 
488 	//--------------------------------------------------------------------
impl_reloadDocument_nothrow(bool _bMigrationSuccess)489     void MacroMigrationDialog::impl_reloadDocument_nothrow( bool _bMigrationSuccess )
490     {
491         typedef ::std::pair< Reference< XFrame >, ::rtl::OUString > ViewDescriptor;
492         ::std::list< ViewDescriptor > aViews;
493 
494         try
495         {
496             // the information which is necessary to reload the document
497             ::rtl::OUString                     sDocumentURL ( m_pData->xDocumentModel->getURL()  );
498             ::comphelper::NamedValueCollection  aDocumentArgs( m_pData->xDocumentModel->getArgs() );
499             if ( !_bMigrationSuccess )
500             {
501                 // if the migration was not successful, then reload from the backup
502                 aDocumentArgs.put( "SalvagedFile", m_pData->sSuccessfulBackupLocation );
503                 // reset the modified flag of the document, so the controller can be suspended later
504                 Reference< XModifiable > xModify( m_pData->xDocument, UNO_QUERY_THROW );
505                 xModify->setModified( sal_False );
506                 // after this reload, don't show the migration warning, again
507                 aDocumentArgs.put( "SuppressMigrationWarning", sal_Bool(sal_True) );
508             }
509 
510             // remove anything from the args which might refer to the old document
511             aDocumentArgs.remove( "Model" );
512             aDocumentArgs.remove( "Stream" );
513             aDocumentArgs.remove( "InputStream" );
514             aDocumentArgs.remove( "FileName" );
515             aDocumentArgs.remove( "URL" );
516 
517             // collect all controllers of our document
518             ::std::list< Reference< XController2 > > aControllers;
519             lcl_getControllers_throw( m_pData->xDocumentModel, aControllers );
520 
521             // close all those controllers
522             while ( !aControllers.empty() )
523             {
524                 Reference< XController2 > xController( aControllers.front(), UNO_SET_THROW );
525                 aControllers.pop_front();
526 
527                 Reference< XFrame > xFrame( xController->getFrame(), UNO_SET_THROW );
528                 ::rtl::OUString sViewName( xController->getViewControllerName() );
529 
530                 if ( !xController->suspend( sal_True ) )
531                 {   // ouch. There shouldn't be any modal dialogs and such, so there
532                     // really is no reason why suspending shouldn't work.
533                     OSL_ENSURE( false, "MacroMigrationDialog::impl_reloadDocument_nothrow: could not suspend a controller!" );
534                     // ignoring this would be at the cost of a crash (potentially)
535                     // so, we cannot continue here.
536                     throw CloseVetoException();
537                 }
538 
539                 aViews.push_back( ViewDescriptor( xFrame, sViewName ) );
540                 xFrame->setComponent( NULL, NULL );
541                 xController->dispose();
542             }
543 
544             // Note the document is closed now - disconnecting the last controller
545             // closes it automatically.
546 
547             Reference< XOfficeDatabaseDocument > xNewDocument;
548 
549             // re-create the views
550             while ( !aViews.empty() )
551             {
552                 ViewDescriptor aView( aViews.front() );
553                 aViews.pop_front();
554 
555                 // load the document into this frame
556                 Reference< XComponentLoader > xLoader( aView.first, UNO_QUERY_THROW );
557                 aDocumentArgs.put( "ViewName", aView.second );
558                 Reference< XInterface > xReloaded( xLoader->loadComponentFromURL(
559                     sDocumentURL,
560                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_self" ) ),
561                     0,
562                     aDocumentArgs.getPropertyValues()
563                 ) );
564 
565                 OSL_ENSURE( xReloaded != m_pData->xDocumentModel,
566                     "MacroMigrationDialog::impl_reloadDocument_nothrow: this should have been a new instance!" );
567                     // this would be unexpected, but recoverable: The loader should at least have done
568                     // this: really *load* the document, even if it loaded it into the old document instance
569                 if ( !xNewDocument.is() )
570                 {
571                     xNewDocument.set( xReloaded, UNO_QUERY_THROW );
572                     // for subsequent loads, into different frames, put the document into the load args
573                     aDocumentArgs.put( "Model", xNewDocument );
574                 }
575                 #if OSL_DEBUG_LEVEL > 0
576                 else
577                 {
578                     OSL_ENSURE( xNewDocument == xReloaded,
579                         "MacroMigrationDialog::impl_reloadDocument_nothrow: unexpected: subsequent load attempt returned a wrong document!" );
580                 }
581                 #endif
582             }
583 
584             m_pData->xDocument = xNewDocument;
585             m_pData->xDocumentModel.set( xNewDocument, UNO_QUERY );
586 
587             // finally, now that the document has been reloaded - if the migration was not successful,
588             // then it was reloaded from the backup, but the real document still is broken. So, save
589             // the document once, which will write the content loaded from the backup to the real docfile.
590             if ( !_bMigrationSuccess )
591             {
592                 Reference< XModifiable > xModify( m_pData->xDocument, UNO_QUERY_THROW );
593                 xModify->setModified( sal_True );
594                     // this is just parnoia - in case saving the doc fails, perhaps the user is tempted to do so
595                 Reference< XStorable > xStor( m_pData->xDocument, UNO_QUERY_THROW );
596                 xStor->store();
597             }
598         }
599         catch( const Exception& )
600         {
601         	DBG_UNHANDLED_EXCEPTION();
602         }
603 
604         // close all frames from aViews - the respective controllers have been closed, but
605         // reloading didn't work, so the frames are zombies now.
606         while ( !aViews.empty() )
607         {
608             ViewDescriptor aView( aViews.front() );
609             aViews.pop_front();
610             try
611             {
612                 Reference< XCloseable > xFrameClose( aView.first, UNO_QUERY_THROW );
613                 xFrameClose->close( sal_True );
614             }
615             catch( const Exception& )
616             {
617         	    DBG_UNHANDLED_EXCEPTION();
618             }
619         }
620     }
621 
622 //........................................................................
623 } // namespace dbmm
624 //........................................................................
625