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