diff options
author | Oliver Bolte <obo@openoffice.org> | 2008-10-16 06:57:26 +0000 |
---|---|---|
committer | Oliver Bolte <obo@openoffice.org> | 2008-10-16 06:57:26 +0000 |
commit | 83da8a29dd96d46cc4e65f673b31d2fd999882ed (patch) | |
tree | 3cf61dfe51fec5bf012767979c232c59a3131069 /dbaccess/source/ext | |
parent | f56058657facb7e5e8f3fe13ffef5d9ea158b79e (diff) |
CWS-TOOLING: integrate CWS odbmacros3
Diffstat (limited to 'dbaccess/source/ext')
22 files changed, 2983 insertions, 377 deletions
diff --git a/dbaccess/source/ext/macromigration/dbmm_global.hrc b/dbaccess/source/ext/macromigration/dbmm_global.hrc index 5084a025e..7bc71199c 100644 --- a/dbaccess/source/ext/macromigration/dbmm_global.hrc +++ b/dbaccess/source/ext/macromigration/dbmm_global.hrc @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: dbmm_global.hrc,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.5 $ * * This file is part of OpenOffice.org. * @@ -47,6 +47,12 @@ #define DLG_MACRO_MIGRATION RID_DBMM_DIALOG_START + 0 //===================================================================== +//= error boxes +//===================================================================== + +#define ERR_INVALID_BACKUP_LOCATION RID_DBMM_DIALOG_START + 0 + +//===================================================================== //= tab pages //===================================================================== @@ -59,17 +65,22 @@ //= strings //===================================================================== -#define STR_FORM ( RID_DBMM_STRING_START + 0 ) -#define STR_REPORT ( RID_DBMM_STRING_START + 1 ) -#define STR_OVERALL_PROGRESS ( RID_DBMM_STRING_START + 2 ) -#define STR_DATABASE_DOCUMENT ( RID_DBMM_STRING_START + 3 ) -#define STR_SAVED_COPY_TO ( RID_DBMM_STRING_START + 4 ) -#define STR_MOVED_LIBRARY ( RID_DBMM_STRING_START + 5 ) -#define STR_OOO_BASIC ( RID_DBMM_STRING_START + 6 ) -#define STR_JAVA_SCRIPT ( RID_DBMM_STRING_START + 7 ) -#define STR_BEAN_SHELL ( RID_DBMM_STRING_START + 8 ) -#define STR_JAVA ( RID_DBMM_STRING_START + 9 ) -#define STR_PYTHON ( RID_DBMM_STRING_START + 10 ) -#define STR_DIALOG ( RID_DBMM_STRING_START + 11 ) +#define STR_FORM ( RID_DBMM_STRING_START + 0 ) +#define STR_REPORT ( RID_DBMM_STRING_START + 1 ) +#define STR_OVERALL_PROGRESS ( RID_DBMM_STRING_START + 2 ) +#define STR_DATABASE_DOCUMENT ( RID_DBMM_STRING_START + 3 ) +#define STR_SAVED_COPY_TO ( RID_DBMM_STRING_START + 4 ) +#define STR_MOVED_LIBRARY ( RID_DBMM_STRING_START + 5 ) +#define STR_OOO_BASIC ( RID_DBMM_STRING_START + 6 ) +#define STR_JAVA_SCRIPT ( RID_DBMM_STRING_START + 7 ) +#define STR_BEAN_SHELL ( RID_DBMM_STRING_START + 8 ) +#define STR_JAVA ( RID_DBMM_STRING_START + 9 ) +#define STR_PYTHON ( RID_DBMM_STRING_START + 10 ) +#define STR_DIALOG ( RID_DBMM_STRING_START + 11 ) +#define STR_MIGRATING_LIBS ( RID_DBMM_STRING_START + 12 ) +#define STR_ERRORS ( RID_DBMM_STRING_START + 13 ) +#define STR_WARNINGS ( RID_DBMM_STRING_START + 14 ) +#define STR_EXCEPTION ( RID_DBMM_STRING_START + 15 ) +#define STR_LIBRARY_TYPE_AND_NAME ( RID_DBMM_STRING_START + 16 ) #endif // DBACCESS_DBMM_GLOBAL_HRC diff --git a/dbaccess/source/ext/macromigration/dbmm_types.cxx b/dbaccess/source/ext/macromigration/dbmm_types.cxx new file mode 100644 index 000000000..68916437d --- /dev/null +++ b/dbaccess/source/ext/macromigration/dbmm_types.cxx @@ -0,0 +1,66 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2008 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* $RCSfile: dbmm_types.cxx,v $ +* +* $Revision: 1.1.2.1 $ +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "dbmm_types.hxx" + +#include "dbmm_global.hrc" +#include "dbmm_module.hxx" + +//........................................................................ +namespace dbmm +{ +//........................................................................ + + //==================================================================== + //= helper + //==================================================================== + //-------------------------------------------------------------------- + String getScriptTypeDisplayName( const ScriptType _eType ) + { + USHORT nResId( 0 ); + + switch ( _eType ) + { + case eBasic: nResId = STR_OOO_BASIC; break; + case eBeanShell: nResId = STR_BEAN_SHELL; break; + case eJavaScript: nResId = STR_JAVA_SCRIPT; break; + case ePython: nResId = STR_PYTHON; break; + case eJava: nResId = STR_JAVA; break; + case eDialog: nResId = STR_DIALOG; break; + } + OSL_ENSURE( nResId != 0, "getScriptTypeDisplayName: illegal script type!" ); + return nResId ? String( MacroMigrationResId( nResId ) ) : String(); + } + +//........................................................................ +} // namespace dbmm +//........................................................................ diff --git a/dbaccess/source/ext/macromigration/dbmm_types.hxx b/dbaccess/source/ext/macromigration/dbmm_types.hxx index f42c47cea..ec53f6f02 100644 --- a/dbaccess/source/ext/macromigration/dbmm_types.hxx +++ b/dbaccess/source/ext/macromigration/dbmm_types.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: dbmm_types.hxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.1 $ * * This file is part of OpenOffice.org. * @@ -31,8 +31,7 @@ #ifndef DBACCESS_DBMM_TYPES_HXX #define DBACCESS_DBMM_TYPES_HXX -/** === begin UNO includes === **/ -/** === end UNO includes === **/ +#include <tools/string.hxx> //........................................................................ namespace dbmm @@ -61,6 +60,11 @@ namespace dbmm eReport }; + //==================================================================== + //= helper + //==================================================================== + String getScriptTypeDisplayName( const ScriptType _eType ); + //........................................................................ } // namespace dbmm //........................................................................ diff --git a/dbaccess/source/ext/macromigration/docerrorhandling.cxx b/dbaccess/source/ext/macromigration/docerrorhandling.cxx deleted file mode 100644 index c98404a76..000000000 --- a/dbaccess/source/ext/macromigration/docerrorhandling.cxx +++ /dev/null @@ -1,91 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: docerrorhandling.cxx,v $ - * $Revision: 1.3 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_dbaccess.hxx" - -#include "docerrorhandling.hxx" - -/** === begin UNO includes === **/ -#include <com/sun/star/task/XInteractionHandler.hpp> -#include <com/sun/star/frame/XModel.hpp> -/** === end UNO includes === **/ - -#include <comphelper/componentcontext.hxx> -#include <comphelper/namedvaluecollection.hxx> -#include <comphelper/interaction.hxx> -#include <tools/diagnose_ex.h> - -//........................................................................ -namespace dbmm -{ -//........................................................................ - - /** === begin UNO using === **/ - using ::com::sun::star::uno::Reference; - using ::com::sun::star::uno::XInterface; - using ::com::sun::star::uno::UNO_QUERY; - using ::com::sun::star::uno::UNO_QUERY_THROW; - using ::com::sun::star::uno::UNO_SET_THROW; - using ::com::sun::star::uno::Exception; - using ::com::sun::star::uno::RuntimeException; - using ::com::sun::star::uno::Any; - using ::com::sun::star::uno::makeAny; - using ::com::sun::star::sdb::XOfficeDatabaseDocument; - using ::com::sun::star::task::XInteractionHandler; - using ::com::sun::star::frame::XModel; - /** === end UNO using === **/ - - //==================================================================== - //= DocumentErrorHandling - //==================================================================== - //-------------------------------------------------------------------- - void DocumentErrorHandling::reportError( const ::comphelper::ComponentContext& _rContext, const Reference< XOfficeDatabaseDocument >& _rxDocument, const Any& _rError ) - { - try - { - Reference< XInteractionHandler > xHandler( _rContext.createComponent( "com.sun.star.task.InteractionHandler" ), UNO_QUERY_THROW ); - // check whether the DB doc has an own interaction handler set - Reference< XModel > xDocModel( _rxDocument, UNO_QUERY_THROW ); - ::comphelper::NamedValueCollection aDocArgs( xDocModel->getArgs() ); - xHandler = aDocArgs.getOrDefault( "InteractionHandler", xHandler ); - xHandler->handle( - new ::comphelper::OInteractionRequest( _rError ) - ); - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } - } - -//........................................................................ -} // namespace dbmm -//........................................................................ diff --git a/dbaccess/source/ext/macromigration/docerrorhandling.hxx b/dbaccess/source/ext/macromigration/docerrorhandling.hxx deleted file mode 100644 index 5e3f18fc7..000000000 --- a/dbaccess/source/ext/macromigration/docerrorhandling.hxx +++ /dev/null @@ -1,69 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: docerrorhandling.hxx,v $ - * $Revision: 1.3 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#ifndef DBACCESS_DOCERRORHANDLING_HXX -#define DBACCESS_DOCERRORHANDLING_HXX - -/** === begin UNO includes === **/ -#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp> -/** === end UNO includes === **/ - -namespace comphelper { - class ComponentContext; -} - -//........................................................................ -namespace dbmm -{ -//........................................................................ - - //==================================================================== - //= DocumentErrorHandling - //==================================================================== - class DocumentErrorHandling - { - public: - /** reports the given error (usually an exception caught on the caller's side) - to the user, using the document's interaction handler, if present. If the document - does not have an own interaction handler, the given component context is used - to create a new one. - */ - static void reportError( - const ::comphelper::ComponentContext& _rContext, - const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XOfficeDatabaseDocument >& _rxDocument, - const ::com::sun::star::uno::Any& _rError - ); - }; - -//........................................................................ -} // namespace dbmm -//........................................................................ - -#endif // DBACCESS_DOCERRORHANDLING_HXX diff --git a/dbaccess/source/ext/macromigration/docinteraction.cxx b/dbaccess/source/ext/macromigration/docinteraction.cxx new file mode 100644 index 000000000..19d1f682f --- /dev/null +++ b/dbaccess/source/ext/macromigration/docinteraction.cxx @@ -0,0 +1,157 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: docinteraction.cxx,v $ + * $Revision: 1.1.2.2 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "docinteraction.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/task/DocumentPasswordRequest.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/interaction.hxx> +#include <rtl/ref.hxx> +#include <tools/diagnose_ex.h> + +//........................................................................ +namespace dbmm +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::task::XInteractionHandler; + using ::com::sun::star::frame::XModel; + using ::com::sun::star::task::DocumentPasswordRequest; + using ::com::sun::star::task::InteractionClassification_QUERY; + using ::com::sun::star::task::PasswordRequestMode_PASSWORD_ENTER; + using ::com::sun::star::task::PasswordRequestMode_PASSWORD_REENTER; + /** === end UNO using === **/ + + //==================================================================== + //= InteractionHandler_Data + //==================================================================== + struct InteractionHandler_Data + { + Reference< XInteractionHandler > xHandler; + + InteractionHandler_Data( const Reference< XInteractionHandler >& _rxHandler ) + :xHandler( _rxHandler ) + { + } + + InteractionHandler_Data( const ::comphelper::ComponentContext& _rContext ) + :xHandler( _rContext.createComponent( "com.sun.star.task.InteractionHandler" ), UNO_QUERY_THROW ) + { + } + }; + + //==================================================================== + //= InteractionHandler + //==================================================================== + //-------------------------------------------------------------------- + InteractionHandler::InteractionHandler( const ::comphelper::ComponentContext& _rContext ) + :m_pData( new InteractionHandler_Data( _rContext ) ) + { + } + + //-------------------------------------------------------------------- + InteractionHandler::InteractionHandler( const Reference< XInteractionHandler >& _rxHandler ) + :m_pData( new InteractionHandler_Data( _rxHandler ) ) + { + } + + //-------------------------------------------------------------------- + InteractionHandler::InteractionHandler( const ::comphelper::ComponentContext& _rContext, const Reference< XModel >& _rxDocument ) + :m_pData( new InteractionHandler_Data( _rContext ) ) + { + // check whether the doumentc has an own interaction handler set + ::comphelper::NamedValueCollection aDocArgs( _rxDocument->getArgs() ); + m_pData->xHandler = aDocArgs.getOrDefault( "InteractionHandler", m_pData->xHandler ); + } + + //-------------------------------------------------------------------- + InteractionHandler::~InteractionHandler() + { + } + + //-------------------------------------------------------------------- + bool InteractionHandler::requestDocumentPassword( const ::rtl::OUString& _rDocumentName, ::rtl::OUString& _io_rPassword ) + { + // create request + DocumentPasswordRequest aRequest( + ::rtl::OUString(), NULL, + InteractionClassification_QUERY, + _io_rPassword.getLength() ? PasswordRequestMode_PASSWORD_REENTER : PasswordRequestMode_PASSWORD_ENTER, + _rDocumentName + ); + + ::rtl::Reference< ::comphelper::OInteractionRequest > pRequest( new ::comphelper::OInteractionRequest( makeAny( aRequest ) ) ); + ::rtl::Reference< ::comphelper::OInteractionPassword > pPassword( new ::comphelper::OInteractionPassword( _io_rPassword ) ); + ::rtl::Reference< ::comphelper::OInteractionAbort > pAbort( new ::comphelper::OInteractionAbort ); + pRequest->addContinuation( pPassword.get() ); + pRequest->addContinuation( pAbort.get() ); + + // handle + m_pData->xHandler->handle( pRequest.get() ); + + // finish up + if ( pAbort->wasSelected() ) + return false; + + _io_rPassword = pPassword->getPassword(); + return true; + } + + //-------------------------------------------------------------------- + void InteractionHandler::reportError( const Any& _rError ) + { + ::rtl::Reference< ::comphelper::OInteractionRequest > pRequest( new ::comphelper::OInteractionRequest( _rError ) ); + ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove( new ::comphelper::OInteractionApprove ); + pRequest->addContinuation( pApprove.get() ); + + m_pData->xHandler->handle( pRequest.get() ); + } + +//........................................................................ +} // namespace dbmm +//........................................................................ diff --git a/dbaccess/source/ext/macromigration/docinteraction.hxx b/dbaccess/source/ext/macromigration/docinteraction.hxx new file mode 100644 index 000000000..298e06c71 --- /dev/null +++ b/dbaccess/source/ext/macromigration/docinteraction.hxx @@ -0,0 +1,107 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: docinteraction.hxx,v $ + * $Revision: 1.1.2.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef DBACCESS_DOCERRORHANDLING_HXX +#define DBACCESS_DOCERRORHANDLING_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +/** === end UNO includes === **/ + +namespace comphelper { + class ComponentContext; +} + +#include <memory> + +//........................................................................ +namespace dbmm +{ +//........................................................................ + + //==================================================================== + //= DocumentErrorHandling + //==================================================================== + struct InteractionHandler_Data; + /** wraps common operations with an interaction handler. + */ + class InteractionHandler + { + public: + /** creates an interaction handler by instantiating a css.task.InteractionHandler + component at the given component context. + */ + InteractionHandler( const ::comphelper::ComponentContext& _rContext ); + + /** creates an InteractionHandler instance, using the given existing UNO handler. + */ + InteractionHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxHandler ); + + /** creates an interaction handler by instantiating a css.task.InteractionHandler + component at the given component context, or using the given document's interaction handler, + if one is specified in the document's media descriptor. + */ + InteractionHandler( const ::comphelper::ComponentContext& _rContext, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& _rxDocument ); + + /** destructor + */ + ~InteractionHandler(); + + /** requests a document password + @param _rDocumentName + the document name + @param _io_rPassword + the initial password on method entry, the password as entered by the user on method leave + @return + <TRUE/> if and only if the user entered a password, and confirmed with OK, <FALSE/> + if the user aborted the request. + */ + bool requestDocumentPassword( + const ::rtl::OUString& _rDocumentName, + ::rtl::OUString& _io_rPassword + ); + + /** reports the given error (usually an exception caught on the caller's side) + to the user + */ + void reportError( + const ::com::sun::star::uno::Any& _rError + ); + + private: + ::std::auto_ptr< InteractionHandler_Data > m_pData; + }; + +//........................................................................ +} // namespace dbmm +//........................................................................ + +#endif // DBACCESS_DOCERRORHANDLING_HXX diff --git a/dbaccess/source/ext/macromigration/macromigration.hrc b/dbaccess/source/ext/macromigration/macromigration.hrc index 18a9ba8aa..673174f21 100644 --- a/dbaccess/source/ext/macromigration/macromigration.hrc +++ b/dbaccess/source/ext/macromigration/macromigration.hrc @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: macromigration.hrc,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.1 $ * * This file is part of OpenOffice.org. * @@ -93,5 +93,7 @@ #define STR_STATE_BACKUP_DBDOC 2 #define STR_STATE_MIGRATE 3 #define STR_STATE_SUMMARY 4 +#define STR_SUCCESSFUL 5 +#define STR_UNSUCCESSFUL 6 #endif // DBACCESS_MACROMIGRATION_HRC diff --git a/dbaccess/source/ext/macromigration/macromigration.src b/dbaccess/source/ext/macromigration/macromigration.src index aa572c0fe..aca9d8975 100644 --- a/dbaccess/source/ext/macromigration/macromigration.src +++ b/dbaccess/source/ext/macromigration/macromigration.src @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: macromigration.src,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.8 $ * * This file is part of OpenOffice.org. * @@ -88,16 +88,16 @@ TabPage TP_PREPARE TAB_PAGE_HEIGHT - CONTENT_POS_X - TAB_PAGE_CONTENT_MARGIN - ( 2 * FIXED_TEXT_HEIGHT - SPACING_UNRELATED ) ); WordBreak = TRUE; - Text [ en-US ] = "This wizard will guide you through the task of migrating your macros and scripts.\n\n" + Text [ en-US ] = "This wizard will guide you through the task of migrating your macros.\n\n" - "After you finished it, all macros and scripts which were formerly embedded into your " - "forms and reports will have been moved to the database document. In this course, libraries " - "will be renamed as needed.\n\n" + "After you finished it, all macros which were formerly embedded into the forms and reports of " + "the current database document will have been moved to the document itself. In this course, " + "libraries will be renamed as needed.\n\n" - "If your forms and reports contain references to those macros and scripts, they " - "will be adjusted, where possible.\n\n" + "If your forms and reports contain references to those macros, they will be adjusted, where " + "possible.\n\n" - "Before the migration can start, all forms, reports, queries and tables must be closed. " + "Before the migration can start, all forms, reports, queries and tables belonging to the document must be closed. " "Press 'Next' to do so."; }; @@ -231,8 +231,6 @@ TabPage TP_MIGRATE Pos = MAP_APPFONT( TAB_PAGE_CONTENT_MARGIN + 60, CONTENT_POS_X + 2 * FIXED_TEXT_HEIGHT + SPACING_UNRELATED ); Size = MAP_APPFONT( TAB_PAGE_WIDTH - ( TAB_PAGE_CONTENT_MARGIN + 60 ), FIXED_TEXT_HEIGHT ); - - Text [ en-US ] = "Form 1"; }; FixedText FT_CURRENT_PROGRESS_LABEL @@ -249,8 +247,6 @@ TabPage TP_MIGRATE Pos = MAP_APPFONT( TAB_PAGE_CONTENT_MARGIN + 60, CONTENT_POS_X + 2 * FIXED_TEXT_HEIGHT + SPACING_UNRELATED + FIXED_TEXT_HEIGHT + SPACING_UNRELATED ); Size = MAP_APPFONT( TAB_PAGE_WIDTH - ( TAB_PAGE_CONTENT_MARGIN + 60 ), FIXED_TEXT_HEIGHT ); - - Text [ en-US ] = "loading ..."; }; Window WND_CURRENT_PROGRESS @@ -299,8 +295,9 @@ TabPage TP_MIGRATE Size = MAP_APPFONT( TAB_PAGE_WIDTH - 2 * TAB_PAGE_CONTENT_MARGIN, 2 * FIXED_TEXT_HEIGHT ); WordBreak = TRUE; + Hide = TRUE; - Text [ en-US ] = "All documents have been successfully processed. Press 'Next' to show a detailed summary."; + Text [ en-US ] = "All forms and reports have been successfully processed. Press 'Next' to show a detailed summary."; }; }; @@ -328,7 +325,7 @@ TabPage TP_SUMMARY Pos = MAP_APPFONT( TAB_PAGE_CONTENT_MARGIN, CONTENT_POS_X ); Size = MAP_APPFONT( TAB_PAGE_WIDTH - 2 * TAB_PAGE_CONTENT_MARGIN, FIXED_TEXT_HEIGHT ); - Text [ en-US ] = "The following actions have been taken:"; + WordBreak = TRUE; }; MultiLineEdit ED_CHANGES @@ -342,6 +339,15 @@ TabPage TP_SUMMARY Border = TRUE; BorderStyle = WINDOW_BORDER_MONO; }; + + String STR_SUCCESSFUL + { + Text [ en-US ] = "The migration was successful. Below is a log of the actions which have been taken to your document."; + }; + String STR_UNSUCCESSFUL + { + Text [ en-US ] = "The migration was not successful. Examine the migration log below for details."; + }; }; String STR_FORM @@ -373,12 +379,22 @@ String STR_SAVED_COPY_TO String STR_MOVED_LIBRARY { - Text[ en-US ] = "moved $type$ library $old$ to $new$"; + Text[ en-US ] = "migrated $type$ library '$old$' to '$new$'"; +}; + +String STR_LIBRARY_TYPE_AND_NAME +{ + Text [ en-US ] = "$type$ library '$library$'"; +}; + +String STR_MIGRATING_LIBS +{ + Text [ en-US ] = "migrating libraries ..."; }; String STR_OOO_BASIC { - Text[ en-US ] = "%PRODUCTNAME% Basic"; + Text[ en-US ] = "%PRODUCTNAME Basic"; }; String STR_JAVA_SCRIPT @@ -406,3 +422,24 @@ String STR_DIALOG Text[ en-US ] = "dialog"; }; +String STR_ERRORS +{ + Text [ en-US ] = "Error(s)"; +}; + +String STR_WARNINGS +{ + Text [ en-US ] = "Warnings"; +}; + +String STR_EXCEPTION +{ + Text [ en-US ] = "caught exception: "; +}; + + +ErrorBox ERR_INVALID_BACKUP_LOCATION +{ + Buttons = WB_OK; + Message [ en-US ] = "You need to choose a backup location other than the document location itself."; +}; diff --git a/dbaccess/source/ext/macromigration/macromigrationdialog.cxx b/dbaccess/source/ext/macromigration/macromigrationdialog.cxx index 7f18ad760..a7432cb71 100644 --- a/dbaccess/source/ext/macromigration/macromigrationdialog.cxx +++ b/dbaccess/source/ext/macromigration/macromigrationdialog.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: macromigrationdialog.cxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.9 $ * * This file is part of OpenOffice.org. * @@ -33,23 +33,36 @@ #include "dbmm_global.hrc" #include "dbmm_module.hxx" -#include "docerrorhandling.hxx" +#include "docinteraction.hxx" #include "macromigration.hrc" #include "macromigrationdialog.hxx" #include "macromigrationpages.hxx" #include "migrationengine.hxx" +#include "migrationerror.hxx" #include "migrationlog.hxx" /** === begin UNO includes === **/ #include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp> #include <com/sun/star/frame/XModel2.hpp> #include <com/sun/star/frame/XStorable.hpp> -#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/ucb/XContent.hpp> +#include <com/sun/star/ucb/XContentProvider.hpp> /** === end UNO includes === **/ +#include <comphelper/namedvaluecollection.hxx> #include <cppuhelper/exc_hlp.hxx> +#include <cppuhelper/implbase1.hxx> +#include <rtl/ref.hxx> #include <svtools/filenotation.hxx> #include <tools/diagnose_ex.h> +#include <ucbhelper/content.hxx> +#include <ucbhelper/contentbroker.hxx> +#include <vcl/msgbox.hxx> + +#include <list> //........................................................................ namespace dbmm @@ -61,7 +74,7 @@ namespace dbmm #define STATE_MIGRATE 2 #define STATE_SUMMARY 3 -#define PATH_DEFAULT 1 +#define PATH_DEFAULT 1 /** === begin UNO using === **/ using ::com::sun::star::uno::Reference; @@ -77,14 +90,39 @@ namespace dbmm using ::com::sun::star::sdb::XOfficeDatabaseDocument; using ::com::sun::star::frame::XModel2; using ::com::sun::star::frame::XController; + using ::com::sun::star::frame::XController2; using ::com::sun::star::container::XEnumeration; using ::com::sun::star::frame::XStorable; using ::com::sun::star::uno::Sequence; using ::com::sun::star::beans::PropertyValue; - using ::com::sun::star::frame::XModel; + using ::com::sun::star::frame::XFrame; + using ::com::sun::star::awt::XWindow; + using ::com::sun::star::util::XCloseable; + using ::com::sun::star::util::XCloseListener; + using ::com::sun::star::util::CloseVetoException; + using ::com::sun::star::lang::EventObject; + using ::com::sun::star::frame::XComponentLoader; + using ::com::sun::star::util::XModifiable; + using ::com::sun::star::ucb::XCommandEnvironment; + using ::com::sun::star::ucb::XContent; + using ::com::sun::star::ucb::XContentIdentifier; + using ::com::sun::star::ucb::XContentProvider; /** === end UNO using === **/ //==================================================================== + //= helper + //==================================================================== + //-------------------------------------------------------------------- + static void lcl_getControllers_throw( const Reference< XModel2 >& _rxDocument, + ::std::list< Reference< XController2 > >& _out_rControllers ) + { + _out_rControllers.clear(); + Reference< XEnumeration > xControllerEnum( _rxDocument->getControllers(), UNO_SET_THROW ); + while ( xControllerEnum->hasMoreElements() ) + _out_rControllers.push_back( Reference< XController2 >( xControllerEnum->nextElement(), UNO_QUERY_THROW ) ); + } + + //==================================================================== //= MacroMigrationDialog_Data //==================================================================== struct MacroMigrationDialog_Data @@ -92,7 +130,11 @@ namespace dbmm ::comphelper::ComponentContext aContext; MigrationLog aLogger; Reference< XOfficeDatabaseDocument > xDocument; + Reference< XModel2 > xDocumentModel; + ::rtl::OUString sSuccessfulBackupLocation; bool bMigrationIsRunning; + bool bMigrationFailure; + bool bMigrationSuccess; MacroMigrationDialog_Data( const ::comphelper::ComponentContext& _rContext, @@ -100,12 +142,14 @@ namespace dbmm :aContext( _rContext ) ,aLogger() ,xDocument( _rxDocument ) + ,xDocumentModel( _rxDocument, UNO_QUERY ) ,bMigrationIsRunning( false ) + ,bMigrationFailure( false ) + ,bMigrationSuccess( false ) { } }; - //==================================================================== //= MacroMigrationDialog //==================================================================== @@ -136,7 +180,7 @@ namespace dbmm enableButtons( WZB_FINISH, true ); ActivatePage(); - OSL_PRECOND( m_pData->xDocument.is(), "MacroMigrationDialog::MacroMigrationDialog: illegal document!" ); + OSL_PRECOND( m_pData->xDocumentModel.is(), "MacroMigrationDialog::MacroMigrationDialog: illegal document!" ); } //-------------------------------------------------------------------- @@ -157,6 +201,21 @@ namespace dbmm } //-------------------------------------------------------------------- + short MacroMigrationDialog::Execute() + { + short nResult = MacroMigrationDialog_Base::Execute(); + if ( !m_pData->bMigrationFailure && !m_pData->bMigrationSuccess ) + // migration did not even start + return nResult; + + OSL_ENSURE( !m_pData->bMigrationFailure || !m_pData->bMigrationSuccess, + "MacroMigrationDialog::Execute: success *and* failure at the same time?!" ); + impl_reloadDocument_nothrow( m_pData->bMigrationSuccess ); + + return nResult; + } + + //-------------------------------------------------------------------- BOOL MacroMigrationDialog::Close() { if ( m_pData->bMigrationIsRunning ) @@ -194,18 +253,23 @@ namespace dbmm enableButtons( WZB_FINISH | WZB_CANCEL | WZB_PREVIOUS | WZB_NEXT, false ); - // prevent closing - m_pData->bMigrationIsRunning = true; // start the migration asynchronously PostUserEvent( LINK( this, MacroMigrationDialog, OnStartMigration ) ); } break; case STATE_SUMMARY: - // enable the previous step - we can't return to the actual migration, it already happened (or failed) + // disable the previous step - we can't return to the actual migration, it already happened (or failed) enableState( STATE_MIGRATE, false ); updateTravelUI(); - dynamic_cast< ResultPage& >( *GetPage( STATE_SUMMARY ) ).displaySummary( m_pData->aLogger.getCompleteLog() ); + + // display the results + dynamic_cast< ResultPage& >( *GetPage( STATE_SUMMARY ) ).displayMigrationLog( + m_pData->bMigrationSuccess, m_pData->aLogger.getCompleteLog() ); + + enableButtons( WZB_FINISH, m_pData->bMigrationSuccess ); + enableButtons( WZB_CANCEL, m_pData->bMigrationFailure ); + defaultButton( m_pData->bMigrationSuccess ? WZB_FINISH : WZB_CANCEL ); break; default: @@ -261,21 +325,34 @@ namespace dbmm //-------------------------------------------------------------------- IMPL_LINK( MacroMigrationDialog, OnStartMigration, void*, /*_pNotInterestedIn*/ ) { + // prevent closing + m_pData->bMigrationIsRunning = true; + // initialize migration engine and progress ProgressPage& rProgressPage( dynamic_cast< ProgressPage& >( *GetPage( STATE_MIGRATE ) ) ); MigrationEngine aEngine( m_pData->aContext, m_pData->xDocument, rProgressPage, m_pData->aLogger ); rProgressPage.setDocumentCounts( aEngine.getFormCount(), aEngine.getReportCount() ); // do the migration - bool bSuccess = aEngine.migrateAll(); + m_pData->bMigrationSuccess = aEngine.migrateAll(); + m_pData->bMigrationFailure = !m_pData->bMigrationSuccess; // re-enable the UI - enableButtons( ( bSuccess ? WZB_FINISH | WZB_NEXT : 0 ), true ); - enableState( STATE_SUMMARY, bSuccess ); + enableButtons( WZB_FINISH | WZB_NEXT, true ); + enableState( STATE_SUMMARY, true ); updateTravelUI(); m_pData->bMigrationIsRunning = false; + if ( m_pData->bMigrationSuccess ) + { + rProgressPage.onFinishedSuccessfully(); + } + else + { // if there was an error, show the summary automatically + travelNext(); + } + // outta here return 0L; } @@ -301,16 +378,12 @@ namespace dbmm bool bSuccess = true; try { - ::std::vector< Reference< XController > > aControllers; - // collect all controllers of our document - Reference< XModel2 > xDocument( m_pData->xDocument, UNO_QUERY_THROW ); - Reference< XEnumeration > xControllerEnum( xDocument->getControllers(), UNO_SET_THROW ); - while ( xControllerEnum->hasMoreElements() ) - aControllers.push_back( Reference< XController >( xControllerEnum->nextElement(), UNO_QUERY_THROW ) ); + ::std::list< Reference< XController2 > > aControllers; + lcl_getControllers_throw( m_pData->xDocumentModel, aControllers ); // close all sub documents of all controllers - for ( ::std::vector< Reference< XController > >::const_iterator pos = aControllers.begin(); + for ( ::std::list< Reference< XController2 > >::const_iterator pos = aControllers.begin(); pos != aControllers.end() && bSuccess; ++pos ) @@ -336,16 +409,64 @@ namespace dbmm } //-------------------------------------------------------------------- + namespace + { + bool lcl_equalURLs_nothrow( const ::rtl::OUString& _lhs, const ::rtl::OUString _rhs ) + { + // the cheap situation: the URLs are equal + if ( _lhs == _rhs ) + return true; + + bool bEqual = true; + try + { + ::ucbhelper::Content aContentLHS = ::ucbhelper::Content( _lhs, Reference< XCommandEnvironment >() ); + ::ucbhelper::Content aContentRHS = ::ucbhelper::Content( _rhs, Reference< XCommandEnvironment >() ); + Reference< XContent > xContentLHS( aContentLHS.get(), UNO_SET_THROW ); + Reference< XContent > xContentRHS( aContentRHS.get(), UNO_SET_THROW ); + Reference< XContentIdentifier > xID1( xContentLHS->getIdentifier(), UNO_SET_THROW ); + Reference< XContentIdentifier > xID2( xContentRHS->getIdentifier(), UNO_SET_THROW ); + + ::ucbhelper::ContentBroker* pBroker = ::ucbhelper::ContentBroker::get(); + Reference< XContentProvider > xProvider( + pBroker ? pBroker->getContentProviderInterface() : Reference< XContentProvider >(), UNO_SET_THROW ); + + bEqual = ( 0 == xProvider->compareContentIds( xID1, xID2 ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return bEqual; + } + } + + //-------------------------------------------------------------------- bool MacroMigrationDialog::impl_backupDocument_nothrow() const { - const SaveDBDocPage& rBackupPage = dynamic_cast< const SaveDBDocPage& >( *GetPage( STATE_BACKUP_DBDOC ) ); + if ( !m_pData->xDocumentModel.is() ) + // should never happen, but has been reported as assertion before + return false; + + SaveDBDocPage& rBackupPage = dynamic_cast< SaveDBDocPage& >( *GetPage( STATE_BACKUP_DBDOC ) ); ::rtl::OUString sBackupLocation( rBackupPage.getBackupLocation() ); Any aError; try { + // check that the backup location isn't the same as the document itself + if ( lcl_equalURLs_nothrow( sBackupLocation, m_pData->xDocumentModel->getURL() ) ) + { + ErrorBox aErrorBox( const_cast< MacroMigrationDialog* >( this ), MacroMigrationResId( ERR_INVALID_BACKUP_LOCATION ) ); + aErrorBox.Execute(); + rBackupPage.grabLocationFocus(); + return false; + } + + // store to the backup location const Reference< XStorable > xDocument( getDocument(), UNO_QUERY_THROW ); xDocument->storeToURL( sBackupLocation, Sequence< PropertyValue >() ); + m_pData->sSuccessfulBackupLocation = sBackupLocation; } catch( const Exception& ) { @@ -359,13 +480,152 @@ namespace dbmm } // display the error to the user - DocumentErrorHandling::reportError( m_pData->aContext, m_pData->xDocument, aError ); + InteractionHandler aHandler( m_pData->aContext, m_pData->xDocumentModel.get() ); + aHandler.reportError( aError ); - // TODO: log the error + m_pData->aLogger.logFailure( MigrationError( + ERR_DOCUMENT_BACKUP_FAILED, + sBackupLocation, + aError + ) ); return false; } + //-------------------------------------------------------------------- + void MacroMigrationDialog::impl_reloadDocument_nothrow( bool _bMigrationSuccess ) + { + typedef ::std::pair< Reference< XFrame >, ::rtl::OUString > ViewDescriptor; + ::std::list< ViewDescriptor > aViews; + + try + { + // the information which is necessary to reload the document + ::rtl::OUString sDocumentURL ( m_pData->xDocumentModel->getURL() ); + ::comphelper::NamedValueCollection aDocumentArgs( m_pData->xDocumentModel->getArgs() ); + if ( !_bMigrationSuccess ) + { + // if the migration was not successful, then reload from the backup + aDocumentArgs.put( "SalvagedFile", m_pData->sSuccessfulBackupLocation ); + // reset the modified flag of the document, so the controller can be suspended later + Reference< XModifiable > xModify( m_pData->xDocument, UNO_QUERY_THROW ); + xModify->setModified( sal_False ); + // after this reload, don't show the migration warning, again + aDocumentArgs.put( "SuppressMigrationWarning", sal_Bool(sal_True) ); + } + + // remove anything from the args which might refer to the old document + aDocumentArgs.remove( "Model" ); + aDocumentArgs.remove( "Stream" ); + aDocumentArgs.remove( "InputStream" ); + aDocumentArgs.remove( "FileName" ); + aDocumentArgs.remove( "URL" ); + + // collect all controllers of our document + ::std::list< Reference< XController2 > > aControllers; + lcl_getControllers_throw( m_pData->xDocumentModel, aControllers ); + + // close all those controllers + while ( !aControllers.empty() ) + { + Reference< XController2 > xController( aControllers.front(), UNO_SET_THROW ); + aControllers.pop_front(); + + Reference< XFrame > xFrame( xController->getFrame(), UNO_SET_THROW ); + ::rtl::OUString sViewName( xController->getViewControllerName() ); + + if ( !xController->suspend( sal_True ) ) + { // ouch. There shouldn't be any modal dialogs and such, so there + // really is no reason why suspending shouldn't work. + OSL_ENSURE( false, "MacroMigrationDialog::impl_reloadDocument_nothrow: could not suspend a controller!" ); + // ignoring this would be at the cost of a crash (potentially) + // so, we cannot continue here. + throw CloseVetoException(); + } + + aViews.push_back( ViewDescriptor( xFrame, sViewName ) ); + xFrame->setComponent( NULL, NULL ); + xController->dispose(); + } + + // Note the document is closed now - disconnecting the last controller + // closes it automatically. + + Reference< XOfficeDatabaseDocument > xNewDocument; + + // re-create the views + while ( !aViews.empty() ) + { + ViewDescriptor aView( aViews.front() ); + aViews.pop_front(); + + // load the document into this frame + Reference< XComponentLoader > xLoader( aView.first, UNO_QUERY_THROW ); + aDocumentArgs.put( "ViewName", aView.second ); + Reference< XInterface > xReloaded( xLoader->loadComponentFromURL( + sDocumentURL, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_self" ) ), + 0, + aDocumentArgs.getPropertyValues() + ) ); + + OSL_ENSURE( xReloaded != m_pData->xDocumentModel, + "MacroMigrationDialog::impl_reloadDocument_nothrow: this should have been a new instance!" ); + // this would be unexpected, but recoverable: The loader should at least have done + // this: really *load* the document, even if it loaded it into the old document instance + if ( !xNewDocument.is() ) + { + xNewDocument.set( xReloaded, UNO_QUERY_THROW ); + // for subsequent loads, into different frames, put the document into the load args + aDocumentArgs.put( "Model", xNewDocument ); + } + #if OSL_DEBUG_LEVEL > 0 + else + { + OSL_ENSURE( xNewDocument == xReloaded, + "MacroMigrationDialog::impl_reloadDocument_nothrow: unexpected: subsequent load attempt returned a wrong document!" ); + } + #endif + } + + m_pData->xDocument = xNewDocument; + m_pData->xDocumentModel.set( xNewDocument, UNO_QUERY ); + + // finally, now that the document has been reloaded - if the migration was not successful, + // then it was reloaded from the backup, but the real document still is broken. So, save + // the document once, which will write the content loaded from the backup to the real docfile. + if ( !_bMigrationSuccess ) + { + Reference< XModifiable > xModify( m_pData->xDocument, UNO_QUERY_THROW ); + xModify->setModified( sal_True ); + // this is just parnoia - in case saving the doc fails, perhaps the user is tempted to do so + Reference< XStorable > xStor( m_pData->xDocument, UNO_QUERY_THROW ); + xStor->store(); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + // close all frames from aViews - the respective controllers have been closed, but + // reloading didn't work, so the frames are zombies now. + while ( !aViews.empty() ) + { + ViewDescriptor aView( aViews.front() ); + aViews.pop_front(); + try + { + Reference< XCloseable > xFrameClose( aView.first, UNO_QUERY_THROW ); + xFrameClose->close( sal_True ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + } + //........................................................................ } // namespace dbmm //........................................................................ diff --git a/dbaccess/source/ext/macromigration/macromigrationdialog.hxx b/dbaccess/source/ext/macromigration/macromigrationdialog.hxx index 2fb747bcf..e3f3d100d 100644 --- a/dbaccess/source/ext/macromigration/macromigrationdialog.hxx +++ b/dbaccess/source/ext/macromigration/macromigrationdialog.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: macromigrationdialog.hxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.1 $ * * This file is part of OpenOffice.org. * @@ -75,11 +75,13 @@ namespace dbmm // Dialog overridables virtual BOOL Close(); + virtual short Execute(); private: void impl_showCloseDocsError( bool _bShow ); bool impl_closeSubDocs_nothrow(); bool impl_backupDocument_nothrow() const; + void impl_reloadDocument_nothrow( bool _bMigrationSuccess ); private: DECL_LINK( OnStartMigration, void* ); diff --git a/dbaccess/source/ext/macromigration/macromigrationpages.cxx b/dbaccess/source/ext/macromigration/macromigrationpages.cxx index 137414beb..79273fd59 100644 --- a/dbaccess/source/ext/macromigration/macromigrationpages.cxx +++ b/dbaccess/source/ext/macromigration/macromigrationpages.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: macromigrationpages.cxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.4 $ * * This file is part of OpenOffice.org. * @@ -43,6 +43,7 @@ #include <tools/urlobj.hxx> #include <tools/diagnose_ex.h> +#include <vcl/metric.hxx> //........................................................................ namespace dbmm @@ -216,8 +217,8 @@ namespace dbmm ,m_aObjectCount ( this, MacroMigrationResId( FT_OBJECT_COUNT ) ) ,m_aCurrentObjectLabel ( this, MacroMigrationResId( FT_CURRENT_OBJECT_LABEL ) ) ,m_aCurrentObject ( this, MacroMigrationResId( FT_CURRENT_OBJECT ) ) - ,m_aCurrentActionLabel ( this, MacroMigrationResId( FT_CURRENT_PROGRESS_LABEL ) ) - ,m_aCurrentAction ( this, MacroMigrationResId( FT_CURRENT_PROGRESS ) ) + ,m_aCurrentActionLabel ( this, MacroMigrationResId( FT_CURRENT_PROGRESS_LABEL ) ) + ,m_aCurrentAction ( this, MacroMigrationResId( FT_CURRENT_PROGRESS ) ) ,m_aCurrentProgress ( this, MacroMigrationResId( WND_CURRENT_PROGRESS ) ) ,m_aAllProgressLabel ( this, MacroMigrationResId( FT_ALL_PROGRESS_LABEL ) ) ,m_aAllProgressText ( this, MacroMigrationResId( FT_OBJECT_COUNT_PROGRESS ) ) @@ -243,6 +244,12 @@ namespace dbmm } //-------------------------------------------------------------------- + void ProgressPage::onFinishedSuccessfully() + { + m_aMigrationDone.Show(); + } + + //-------------------------------------------------------------------- void ProgressPage::startObject( const ::rtl::OUString& _rObjectName, const ::rtl::OUString& _rCurrentAction, const sal_uInt32 _nRange ) { m_aCurrentObject.SetText( _rObjectName ); @@ -252,6 +259,8 @@ namespace dbmm // since this is currently called from the main thread, which does not have the chance // to re-schedule, we need to explicitly update the display + m_aCurrentObject.Update(); + m_aCurrentAction.Update(); Update(); } @@ -259,6 +268,7 @@ namespace dbmm void ProgressPage::setObjectProgressText( const ::rtl::OUString& _rText ) { m_aCurrentAction.SetText( _rText ); + m_aCurrentAction.Update(); Update(); } @@ -272,9 +282,9 @@ namespace dbmm //-------------------------------------------------------------------- void ProgressPage::endObject() { - m_aCurrentObject.SetText( String() ); m_aCurrentAction.SetText( String() ); - m_aCurrentProgress.SetValue( (sal_uInt32)0 ); + m_aCurrentProgress.SetValue( m_aCurrentProgress.GetRange() ); + m_aCurrentAction.Update(); Update(); } @@ -307,6 +317,8 @@ namespace dbmm :MacroMigrationPage( _rParentDialog, MacroMigrationResId( TP_SUMMARY ) ) ,m_aChangesLabel( this, MacroMigrationResId( FT_CHANGES_LABEL ) ) ,m_aChanges ( this, MacroMigrationResId( ED_CHANGES ) ) + ,m_aSuccessful ( MacroMigrationResId( STR_SUCCESSFUL ) ) + ,m_aUnsuccessful( MacroMigrationResId( STR_UNSUCCESSFUL ) ) { FreeResource(); } @@ -318,9 +330,30 @@ namespace dbmm } //-------------------------------------------------------------------- - void ResultPage::displaySummary( const String& _rSummary ) + void ResultPage::displayMigrationLog( const bool _bSuccessful, const String& _rSummary ) { + m_aChangesLabel.SetText( _bSuccessful ? m_aSuccessful : m_aUnsuccessful ); m_aChanges.SetText( _rSummary ); + + // resize m_aChangesLabel and m_aChances as needed for the label text to fit + Rectangle aOriginalLabelSize( m_aChangesLabel.GetPosPixel(), m_aChangesLabel.GetSizePixel() ); + // assume 3 lines, at most + Rectangle aNewLabelSize( aOriginalLabelSize ); + aNewLabelSize.Bottom() = aNewLabelSize.Top() + m_aChangesLabel.LogicToPixel( Size( 0, 3*8 ), MAP_APPFONT ).Height(); + TextRectInfo aInfo; + aNewLabelSize = m_aChangesLabel.GetTextRect( aNewLabelSize, m_aChangesLabel.GetText(), TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK, &aInfo ); + aNewLabelSize.Bottom() = aNewLabelSize.Top() + m_aChangesLabel.LogicToPixel( Size( 0, aInfo.GetLineCount() * 8 ), MAP_APPFONT ).Height(); + + m_aChangesLabel.SetSizePixel( aNewLabelSize.GetSize() ); + + long nChangesDiff = aNewLabelSize.GetHeight() - aOriginalLabelSize.GetHeight(); + Size aChangesSize( m_aChanges.GetSizePixel() ); + aChangesSize.Height() -= nChangesDiff; + m_aChanges.SetSizePixel( aChangesSize ); + + Point aChangesPos( m_aChanges.GetPosPixel() ); + aChangesPos.Y() += nChangesDiff; + m_aChanges.SetPosPixel( aChangesPos ); } //........................................................................ diff --git a/dbaccess/source/ext/macromigration/macromigrationpages.hxx b/dbaccess/source/ext/macromigration/macromigrationpages.hxx index d6b7ce28c..0a7063727 100644 --- a/dbaccess/source/ext/macromigration/macromigrationpages.hxx +++ b/dbaccess/source/ext/macromigration/macromigrationpages.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: macromigrationpages.hxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.3 $ * * This file is part of OpenOffice.org. * @@ -100,6 +100,7 @@ namespace dbmm public: ::rtl::OUString getBackupLocation() const { return m_aLocationController.getURL(); } + void grabLocationFocus() { m_aSaveAsLocation.GrabFocus(); } protected: FixedText m_aExplanation; @@ -133,6 +134,7 @@ namespace dbmm static TabPage* Create( ::svt::RoadmapWizard& _rParentDialog ); void setDocumentCounts( const sal_Int32 _nForms, const sal_Int32 _nReports ); + void onFinishedSuccessfully(); protected: // IMigrationProgress @@ -167,11 +169,13 @@ namespace dbmm static TabPage* Create( ::svt::RoadmapWizard& _rParentDialog ); - void displaySummary( const String& _rSummary ); + void displayMigrationLog( const bool _bSuccessful, const String& _rLog ); private: FixedText m_aChangesLabel; MultiLineEdit m_aChanges; + String m_aSuccessful; + String m_aUnsuccessful; }; //........................................................................ diff --git a/dbaccess/source/ext/macromigration/macromigrationwizard.cxx b/dbaccess/source/ext/macromigration/macromigrationwizard.cxx index 1419f8899..77643b8c1 100644 --- a/dbaccess/source/ext/macromigration/macromigrationwizard.cxx +++ b/dbaccess/source/ext/macromigration/macromigrationwizard.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: macromigrationwizard.cxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.2 $ * * This file is part of OpenOffice.org. * @@ -37,6 +37,7 @@ /** === begin UNO includes === **/ #include <com/sun/star/ucb/AlreadyInitializedException.hpp> #include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp> +#include <com/sun/star/frame/XStorable.hpp> /** === end UNO includes === **/ #include <comphelper/componentcontext.hxx> @@ -64,6 +65,7 @@ namespace dbmm using ::com::sun::star::ucb::AlreadyInitializedException; using ::com::sun::star::sdb::XOfficeDatabaseDocument; using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::frame::XStorable; /** === end UNO using === **/ //==================================================================== @@ -209,7 +211,7 @@ namespace dbmm if ( _rArguments.getLength() != 1 ) throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid number of initialization arguments. Expected 1." ) ), - // TODO: resoource + // TODO: resource *this, 1 ); @@ -223,6 +225,15 @@ namespace dbmm 1 ); + Reference< XStorable > xDocStor( m_xDocument, UNO_QUERY_THROW ); + if ( xDocStor->isReadonly() ) + throw IllegalArgumentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Not applicable to read-only documents." ) ), + // TODO: resource + *this, + 1 + ); + m_bInitialized = true; } diff --git a/dbaccess/source/ext/macromigration/makefile.mk b/dbaccess/source/ext/macromigration/makefile.mk index dba5395c3..3c833332f 100644 --- a/dbaccess/source/ext/macromigration/makefile.mk +++ b/dbaccess/source/ext/macromigration/makefile.mk @@ -8,7 +8,7 @@ # # $RCSfile: makefile.mk,v $ # -# $Revision: 1.3 $ +# $Revision: 1.3.2.4 $ # # This file is part of OpenOffice.org. # @@ -56,9 +56,11 @@ SLOFILES= $(SLO)$/macromigrationwizard.obj \ $(SLO)$/dbmm_module.obj \ $(SLO)$/dbmm_services.obj \ $(SLO)$/migrationengine.obj \ - $(SLO)$/docerrorhandling.obj \ + $(SLO)$/docinteraction.obj \ $(SLO)$/progresscapture.obj \ + $(SLO)$/progressmixer.obj \ $(SLO)$/migrationlog.obj \ + $(SLO)$/dbmm_types.obj \ # --- library ----------------------------------- @@ -75,7 +77,8 @@ SHL1STDLIBS= \ $(SVTOOLLIB) \ $(SVLLIB) \ $(VCLLIB) \ - $(SVXLIB) + $(SVXLIB) \ + $(UCBHELPERLIB) SHL1LIBS= $(SLB)$/$(TARGET).lib SHL1IMPLIB= i$(TARGET) diff --git a/dbaccess/source/ext/macromigration/migrationengine.cxx b/dbaccess/source/ext/macromigration/migrationengine.cxx index 1e3bd0e65..eb3f3c976 100644 --- a/dbaccess/source/ext/macromigration/migrationengine.cxx +++ b/dbaccess/source/ext/macromigration/migrationengine.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: migrationengine.cxx,v $ - * $Revision: 1.4 $ + * $Revision: 1.4.2.14 $ * * This file is part of OpenOffice.org. * @@ -34,11 +34,13 @@ #include "dbmm_global.hrc" #include "dbmm_module.hxx" #include "dbmm_types.hxx" -#include "docerrorhandling.hxx" +#include "docinteraction.hxx" #include "migrationengine.hxx" +#include "migrationerror.hxx" #include "migrationprogress.hxx" #include "migrationlog.hxx" #include "progresscapture.hxx" +#include "progressmixer.hxx" /** === begin UNO includes === **/ #include <com/sun/star/sdb/XFormDocumentsSupplier.hpp> @@ -48,16 +50,38 @@ #include <com/sun/star/frame/XComponentLoader.hpp> #include <com/sun/star/ucb/XCommandProcessor.hpp> #include <com/sun/star/embed/XComponentSupplier.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/document/XStorageBasedDocument.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/embed/XEmbedPersist.hpp> +#include <com/sun/star/script/DocumentScriptLibraryContainer.hpp> +#include <com/sun/star/script/DocumentDialogLibraryContainer.hpp> +#include <com/sun/star/document/XEmbeddedScripts.hpp> +#include <com/sun/star/document/XEventsSupplier.hpp> +#include <com/sun/star/uri/UriReferenceFactory.hpp> +#include <com/sun/star/uri/XVndSunStarScriptUrlReference.hpp> +#include <com/sun/star/form/XFormsSupplier.hpp> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/script/XEventAttacherManager.hpp> +#include <com/sun/star/script/XLibraryContainerPassword.hpp> /** === end UNO includes === **/ -#include <comphelper/string.hxx> +#include <comphelper/documentinfo.hxx> +#include <comphelper/interaction.hxx> #include <comphelper/namedvaluecollection.hxx> +#include <comphelper/string.hxx> +#include <comphelper/types.hxx> +#include <cppuhelper/exc_hlp.hxx> #include <tools/string.hxx> #include <tools/diagnose_ex.h> #include <rtl/ustrbuf.hxx> #include <rtl/ref.hxx> +#include <unotools/sharedunocomponent.hxx> #include <vector> +#include <set> #define DEFAULT_DOC_PROGRESS_RANGE 100000 @@ -90,19 +114,54 @@ namespace dbmm using ::com::sun::star::ucb::Command; using ::com::sun::star::embed::XComponentSupplier; using ::com::sun::star::task::XStatusIndicator; + using ::com::sun::star::embed::XStorage; + using ::com::sun::star::document::XStorageBasedDocument; + using ::com::sun::star::embed::XTransactedObject; + using ::com::sun::star::frame::XStorable; + using ::com::sun::star::embed::XEmbedPersist; + using ::com::sun::star::script::DocumentDialogLibraryContainer; + using ::com::sun::star::script::DocumentScriptLibraryContainer; + using ::com::sun::star::script::XStorageBasedLibraryContainer; + using ::com::sun::star::document::XEmbeddedScripts; + using ::com::sun::star::container::XNameContainer; + using ::com::sun::star::document::XEventsSupplier; + using ::com::sun::star::container::XNameReplace; + using com::sun::star::uri::UriReferenceFactory; + using com::sun::star::uri::XUriReferenceFactory; + using com::sun::star::uri::XVndSunStarScriptUrlReference; + using ::com::sun::star::form::XFormsSupplier; + using ::com::sun::star::drawing::XDrawPageSupplier; + using ::com::sun::star::drawing::XDrawPagesSupplier; + using ::com::sun::star::drawing::XDrawPage; + using ::com::sun::star::drawing::XDrawPages; + using ::com::sun::star::container::XIndexAccess; + using ::com::sun::star::script::XEventAttacherManager; + using ::com::sun::star::script::ScriptEventDescriptor; + using ::com::sun::star::script::XLibraryContainerPassword; /** === end UNO using === **/ + namespace ElementModes = ::com::sun::star::embed::ElementModes; + +// migration phases whose progresses are to be mixed into one progress +#define PHASE_JAVASCRIPT 1 +#define PHASE_BEANSHELL 2 +#define PHASE_PYTHON 3 +#define PHASE_JAVA 4 +#define PHASE_BASIC 5 +#define PHASE_DIALOGS 6 //==================================================================== //= SubDocument //==================================================================== struct SubDocument { - Reference< XCommandProcessor > xCommandProcessor; - ::rtl::OUString sHierarchicalName; - SubDocumentType eType; + Reference< XCommandProcessor > xCommandProcessor; + Reference< XModel > xDocument; // valid only temporarily + ::rtl::OUString sHierarchicalName; + SubDocumentType eType; SubDocument( const Reference< XCommandProcessor >& _rxCommandProcessor, const ::rtl::OUString& _rName, const SubDocumentType _eType ) :xCommandProcessor( _rxCommandProcessor ) + ,xDocument() ,sHierarchicalName( _rName ) ,eType( _eType ) { @@ -112,6 +171,644 @@ namespace dbmm typedef ::std::vector< SubDocument > SubDocuments; //==================================================================== + //= helper + //==================================================================== + //-------------------------------------------------------------------- + typedef ::utl::SharedUNOComponent< XStorage > SharedStorage; + + namespace + { + //---------------------------------------------------------------- + static const ::rtl::OUString& lcl_getScriptsStorageName() + { + static const ::rtl::OUString s_sScriptsStorageName( RTL_CONSTASCII_USTRINGPARAM( "Scripts" ) ); + return s_sScriptsStorageName; + } + + //---------------------------------------------------------------- + static const ::rtl::OUString& lcl_getScriptsSubStorageName( const ScriptType _eType ) + { + static const ::rtl::OUString s_sBeanShell ( RTL_CONSTASCII_USTRINGPARAM( "beanshell" ) ); + static const ::rtl::OUString s_sJavaScript( RTL_CONSTASCII_USTRINGPARAM( "javascript" ) ); + static const ::rtl::OUString s_sPython ( RTL_CONSTASCII_USTRINGPARAM( "python" ) ); // TODO: is this correct? + static const ::rtl::OUString s_sJava ( RTL_CONSTASCII_USTRINGPARAM( "java" ) ); + + switch ( _eType ) + { + case eBeanShell: return s_sBeanShell; + case eJavaScript: return s_sJavaScript; + case ePython: return s_sPython; + case eJava: return s_sJava; + default: + break; + } + + OSL_ENSURE( false, "lcl_getScriptsSubStorageName: illegal type!" ); + static ::rtl::OUString s_sEmpty; + return s_sEmpty; + } + + //---------------------------------------------------------------- + static bool lcl_getScriptTypeFromLanguage( const ::rtl::OUString& _rLanguage, ScriptType& _out_rScriptType ) + { + struct LanguageMapping + { + const sal_Char* pAsciiLanguage; + const ScriptType eScriptType; + + LanguageMapping( const sal_Char* _pAsciiLanguage, const ScriptType _eScriptType ) + :pAsciiLanguage( _pAsciiLanguage ) + ,eScriptType( _eScriptType ) + { + } + } + aLanguageMapping[] = + { + LanguageMapping( "JavaScript", eJavaScript ), + LanguageMapping( "BeanShell", eBeanShell ), + LanguageMapping( "Java", eJava ), + LanguageMapping( "Python", ePython ), // TODO: is this correct? + LanguageMapping( "Basic", eBasic ) + }; + for ( size_t i=0; i < sizeof( aLanguageMapping ) / sizeof( aLanguageMapping[0] ); ++i ) + { + if ( _rLanguage.equalsAscii( aLanguageMapping[i].pAsciiLanguage ) ) + { + _out_rScriptType = aLanguageMapping[i].eScriptType; + return true; + } + } + OSL_ENSURE( false, "lcl_getScriptTypeFromLanguage: unknown language!" ); + return false; + } + + //---------------------------------------------------------------- + ::rtl::OUString lcl_getSubDocumentDescription( const SubDocument& _rDocument ) + { + ::rtl::OUString sObjectName = String( MacroMigrationResId( _rDocument.eType == eForm ? STR_FORM : STR_REPORT ) ); + ::comphelper::string::searchAndReplaceAsciiI( sObjectName, "$name$", _rDocument.sHierarchicalName ); + return sObjectName; + } + + //---------------------------------------------------------------- + static Any lcl_executeCommand_throw( const Reference< XCommandProcessor >& _rxCommandProc, + const sal_Char* _pAsciiCommand ) + { + OSL_PRECOND( _rxCommandProc.is(), "lcl_executeCommand_throw: illegal object!" ); + if ( !_rxCommandProc.is() ) + return Any(); + + Command aCommand; + aCommand.Name = ::rtl::OUString::createFromAscii( _pAsciiCommand ); + return _rxCommandProc->execute( + aCommand, _rxCommandProc->createCommandIdentifier(), NULL ); + } + + //---------------------------------------------------------------- + static bool lcl_loadSubDocument_nothrow( SubDocument& _rDocument, + const Reference< XStatusIndicator >& _rxProgress, MigrationLog& _rLogger ) + { + OSL_PRECOND( !_rDocument.xDocument.is(), "lcl_loadSubDocument_nothrow: already loaded!" ); + + try + { + ::comphelper::NamedValueCollection aLoadArgs; + aLoadArgs.put( "Hidden", (sal_Bool)sal_True ); + aLoadArgs.put( "StatusIndicator", _rxProgress ); + + Reference< XCommandProcessor > xCommandProcessor( _rDocument.xCommandProcessor, UNO_SET_THROW ); + Command aCommand; + aCommand.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "openDesign" ) ); + aCommand.Argument <<= aLoadArgs.getPropertyValues(); + Reference< XComponent > xDocComponent( + xCommandProcessor->execute( + aCommand, xCommandProcessor->createCommandIdentifier(), NULL + ), + UNO_QUERY + ); + OSL_ENSURE( xDocComponent.is(), "lcl_loadSubDocument_nothrow: no component loaded!" ); + + _rDocument.xDocument.set( xDocComponent, UNO_QUERY_THROW ); + } + catch( const Exception& ) + { + _rLogger.logFailure( MigrationError( + ERR_OPENING_SUB_DOCUMENT_FAILED, + lcl_getSubDocumentDescription( _rDocument ), + ::cppu::getCaughtException() + ) ); + } + return _rDocument.xDocument.is(); + } + + //---------------------------------------------------------------- + static bool lcl_unloadSubDocument_nothrow( SubDocument& _rDocument, MigrationLog& _rLogger ) + { + bool bSuccess = false; + Any aException; + try + { + OSL_VERIFY( lcl_executeCommand_throw( _rDocument.xCommandProcessor, "close" ) >>= bSuccess ); + } + catch( const Exception& ) + { + aException = ::cppu::getCaughtException(); + } + + // log the failure, if any + if ( !bSuccess ) + { + _rLogger.logFailure( MigrationError( + ERR_CLOSING_SUB_DOCUMENT_FAILED, + lcl_getSubDocumentDescription( _rDocument ), + aException + ) ); + } + + _rDocument.xDocument.clear(); + return bSuccess; + } + + //---------------------------------------------------------------- + bool lcl_commitStorage_nothrow( const Reference< XStorage >& _rxStorage ) + { + try + { + Reference< XTransactedObject > xTrans( _rxStorage, UNO_QUERY_THROW ); + xTrans->commit(); + } + catch( const Exception& ) + { + return false; + } + return true; + } + + //---------------------------------------------------------------- + bool lcl_commitDocumentStorage_nothrow( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger ) + { + bool bSuccess = false; + Any aException; + try + { + Reference< XStorageBasedDocument > xStorageDoc( _rxDocument, UNO_QUERY_THROW ); + Reference< XStorage > xDocStorage( xStorageDoc->getDocumentStorage(), UNO_QUERY_THROW ); + bSuccess = lcl_commitStorage_nothrow( xDocStorage ); + } + catch( const Exception& ) + { + aException = ::cppu::getCaughtException(); + } + + // log the failure, if any + if ( !bSuccess ) + { + _rLogger.logFailure( MigrationError( + ERR_STORAGE_COMMIT_FAILED, + ::comphelper::DocumentInfo::getDocumentTitle( _rxDocument ), + aException + ) ); + } + return bSuccess; + } + + //---------------------------------------------------------------- + bool lcl_storeDocument_nothrow( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger ) + { + bool bSuccess = false; + Any aException; + try + { + Reference< XStorable > xStorable( _rxDocument, UNO_QUERY_THROW ); + xStorable->store(); + bSuccess = true; + } + catch( const Exception& ) + { + aException = ::cppu::getCaughtException(); + } + + // log the failure, if any + if ( !bSuccess ) + { + _rLogger.logFailure( MigrationError( + ERR_STORING_DATABASEDOC_FAILED, + aException + ) ); + } + return bSuccess; + } + + //---------------------------------------------------------------- + bool lcl_storeEmbeddedDocument_nothrow( const SubDocument& _rDocument ) + { + try + { + lcl_executeCommand_throw( _rDocument.xCommandProcessor, "store" ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + return false; + } + return true; + } + } + + //==================================================================== + //= DrawPageIterator + //==================================================================== + class DrawPageIterator + { + public: + DrawPageIterator( const Reference< XModel >& _rxDocument ) + :m_xDocument( _rxDocument ) + ,m_nPageCount( 0 ) + ,m_nCurrentPage( 0 ) + { + Reference< XDrawPageSupplier > xSingle( _rxDocument, UNO_QUERY ); + Reference< XDrawPagesSupplier > xMulti( _rxDocument, UNO_QUERY ); + if ( xSingle.is() ) + { + m_xSinglePage.set( xSingle->getDrawPage(), UNO_SET_THROW ); + m_nPageCount = 1; + } + else if ( xMulti.is() ) + { + m_xMultiPages.set( xMulti->getDrawPages(), UNO_SET_THROW ); + m_nPageCount = m_xMultiPages->getCount(); + } + } + + bool hasMore() const + { + return m_nCurrentPage < m_nPageCount; + } + + Reference< XDrawPage > next() + { + Reference< XDrawPage > xNextPage; + + if ( m_xSinglePage.is() ) + { + xNextPage = m_xSinglePage; + } + else if ( m_xMultiPages.is() ) + { + xNextPage.set( m_xMultiPages->getByIndex( m_nCurrentPage ), UNO_QUERY_THROW ); + } + ++m_nCurrentPage; + return xNextPage; + } + + private: + const Reference< XModel > m_xDocument; + Reference< XDrawPage > m_xSinglePage; + Reference< XDrawPages > m_xMultiPages; + sal_Int32 m_nPageCount; + sal_Int32 m_nCurrentPage; + }; + + //==================================================================== + //= FormComponentScripts + //==================================================================== + class FormComponentScripts + { + public: + FormComponentScripts( + const Reference< XInterface >& _rxComponent, + const Reference< XEventAttacherManager >& _rxManager, + const sal_Int32 _nIndex + ) + :m_xComponent( _rxComponent, UNO_SET_THROW ) + ,m_xManager( _rxManager, UNO_SET_THROW ) + ,m_nIndex( _nIndex ) + { + } + + Sequence< ScriptEventDescriptor > getEvents() const + { + return m_xManager->getScriptEvents( m_nIndex ); + } + + void setEvents( const Sequence< ScriptEventDescriptor >& _rEvents ) const + { + m_xManager->registerScriptEvents( m_nIndex, _rEvents ); + } + + const Reference< XInterface >& getComponent() const + { + return m_xComponent; + } + + private: + const Reference< XInterface > m_xComponent; + const Reference< XEventAttacherManager > m_xManager; + const sal_Int32 m_nIndex; + }; + + //==================================================================== + //= FormComponentIterator + //==================================================================== + class FormComponentIterator + { + public: + FormComponentIterator( const Reference< XIndexAccess >& _rxContainer ) + :m_xContainer( _rxContainer, UNO_SET_THROW ) + ,m_xEventManager( _rxContainer, UNO_QUERY_THROW ) + ,m_nElementCount( _rxContainer->getCount() ) + ,m_nCurrentElement( 0 ) + { + } + + bool hasMore() const + { + return m_nCurrentElement < m_nElementCount; + } + + FormComponentScripts next() + { + FormComponentScripts aComponent( + Reference< XInterface >( m_xContainer->getByIndex( m_nCurrentElement ), UNO_QUERY_THROW ), + m_xEventManager, + m_nCurrentElement + ); + ++m_nCurrentElement; + return aComponent; + } + + private: + const Reference< XIndexAccess > m_xContainer; + const Reference< XEventAttacherManager > m_xEventManager; + const sal_Int32 m_nElementCount; + sal_Int32 m_nCurrentElement; + + }; + + //==================================================================== + //= ScriptsStorage - declaration + //==================================================================== + /** a helper class which encapsulates access to the storages for Java/Script, BeanShell, and Python scripts, + i.e. all script types which can be manipulated on storage level. + */ + class ScriptsStorage + { + public: + ScriptsStorage( MigrationLog& _rLogger ); + ScriptsStorage( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger ); + ~ScriptsStorage(); + + /** determines whether the instance is valid, i.e. refers to a valid root storage + for reading/storing scripts + */ + inline bool isValid() const { return m_xScriptsStorage.is(); } + + /** binds the instance to a new document. Only to be called when the instance is not yet + bound (i.e. isValid returns <FALSE/>). + */ + void bind( const Reference< XModel >& _rxDocument ); + + /// determines whether scripts of the given type are present + bool hasScripts( const ScriptType _eType ) const; + + /// returns the root storage for the scripts of the given type + SharedStorage + getScriptsRoot( const ScriptType _eType ) const; + + /** returns the names of the elements in the "Scripts" storage + */ + ::std::set< ::rtl::OUString > + getElementNames() const; + + /** removes the sub storage for a given script type + @precond + the respective storage is empty + @precond + the ScriptsStorage instance was opened for writing + */ + void removeScriptTypeStorage( const ScriptType _eType ) const; + + /** commits the changes at our XStorage object + */ + bool commit(); + + /** removes the "Scripts" sub storage from the given document's root storage + @precond + the "Scripts" storage is empty + */ + static bool + removeFromDocument( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger ); + + private: + MigrationLog& m_rLogger; + SharedStorage m_xScriptsStorage; + }; + + //==================================================================== + //= ScriptsStorage - implementation + //==================================================================== + //-------------------------------------------------------------------- + ScriptsStorage::ScriptsStorage( MigrationLog& _rLogger ) + :m_rLogger( _rLogger ) + ,m_xScriptsStorage() + { + } + + //-------------------------------------------------------------------- + ScriptsStorage::ScriptsStorage( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger ) + :m_rLogger( _rLogger ) + ,m_xScriptsStorage() + { + bind( _rxDocument ); + } + + //-------------------------------------------------------------------- + ScriptsStorage::~ScriptsStorage() + { + } + + //-------------------------------------------------------------------- + bool ScriptsStorage::commit() + { + return lcl_commitStorage_nothrow( m_xScriptsStorage ); + } + + //-------------------------------------------------------------------- + void ScriptsStorage::bind( const Reference< XModel >& _rxDocument ) + { + OSL_PRECOND( !isValid(), "ScriptsStorage:bind: did not bother, yet, to check whether this is allowed!" ); + try + { + Reference< XStorageBasedDocument > xStorageDoc( _rxDocument, UNO_QUERY_THROW ); + Reference< XStorage > xDocStorage( xStorageDoc->getDocumentStorage(), UNO_QUERY_THROW ); + + // the the "Scripts" storage exist, or if it does not (yet) exist and we are in write mode + // => open the storage + if ( ( xDocStorage->hasByName( lcl_getScriptsStorageName() ) + && xDocStorage->isStorageElement( lcl_getScriptsStorageName() ) + ) + || !xDocStorage->hasByName( lcl_getScriptsStorageName() ) + ) + { + m_xScriptsStorage.set( + xDocStorage->openStorageElement( + lcl_getScriptsStorageName(), ElementModes::READWRITE + ), + UNO_QUERY_THROW + ); + } + } + catch( const Exception& ) + { + m_rLogger.logFailure( MigrationError( + ERR_BIND_SCRIPT_STORAGE_FAILED, + ::comphelper::DocumentInfo::getDocumentTitle( _rxDocument ), + ::cppu::getCaughtException() + ) ); + } + } + + //-------------------------------------------------------------------- + bool ScriptsStorage::hasScripts( const ScriptType _eType ) const + { + OSL_PRECOND( isValid(), "ScriptsStorage::hasScripts: illegal call!" ); + if ( !isValid() ) + return false; + + const ::rtl::OUString& rSubStorageName( lcl_getScriptsSubStorageName( _eType ) ); + return m_xScriptsStorage->hasByName( rSubStorageName ) + && m_xScriptsStorage->isStorageElement( rSubStorageName ); + } + + //-------------------------------------------------------------------- + SharedStorage ScriptsStorage::getScriptsRoot( const ScriptType _eType ) const + { + SharedStorage xStorage; + if ( isValid() ) + { + xStorage.reset( m_xScriptsStorage->openStorageElement( + lcl_getScriptsSubStorageName( _eType ), ElementModes::READWRITE + ) ); + } + return xStorage; + } + + //-------------------------------------------------------------------- + ::std::set< ::rtl::OUString > ScriptsStorage::getElementNames() const + { + Sequence< ::rtl::OUString > aElementNames; + if ( isValid() ) + aElementNames = m_xScriptsStorage->getElementNames(); + + ::std::set< ::rtl::OUString > aNames; + ::std::copy( + aElementNames.getConstArray(), + aElementNames.getConstArray() + aElementNames.getLength(), + ::std::insert_iterator< ::std::set< ::rtl::OUString > >( aNames, aNames.end() ) + ); + return aNames; + } + + //-------------------------------------------------------------------- + void ScriptsStorage::removeScriptTypeStorage( const ScriptType _eType ) const + { + ::rtl::OUString sSubStorageName( lcl_getScriptsSubStorageName( _eType ) ); + if ( m_xScriptsStorage->hasByName( sSubStorageName ) ) + m_xScriptsStorage->removeElement( sSubStorageName ); + } + + //-------------------------------------------------------------------- + bool ScriptsStorage::removeFromDocument( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger ) + { + try + { + Reference< XStorageBasedDocument > xStorageDoc( _rxDocument, UNO_QUERY_THROW ); + Reference< XStorage > xDocStorage( xStorageDoc->getDocumentStorage(), UNO_QUERY_THROW ); + xDocStorage->removeElement( lcl_getScriptsStorageName() ); + } + catch( const Exception& ) + { + _rLogger.logFailure( MigrationError( + ERR_REMOVE_SCRIPTS_STORAGE_FAILED, + ::comphelper::DocumentInfo::getDocumentTitle( _rxDocument ), + ::cppu::getCaughtException() + ) ) ; + return false; + } + return true; + } + + //==================================================================== + //= ProgressDelegator + //==================================================================== + class ProgressDelegator : public IProgressConsumer + { + public: + ProgressDelegator( IMigrationProgress& _rDelegator, + const ::rtl::OUString& _rObjectName, + const ::rtl::OUString& _rAction + ) + :m_rDelegator( _rDelegator ) + ,m_sObjectName( _rObjectName ) + ,m_sAction( _rAction ) + { + } + virtual ~ProgressDelegator() + { + } + + // IProgressConsumer + virtual void start( sal_uInt32 _nRange ) + { + m_rDelegator.startObject( m_sObjectName, m_sAction, _nRange ); + } + virtual void advance( sal_uInt32 _nValue ) + { + m_rDelegator.setObjectProgressValue( _nValue ); + } + virtual void end() + { + m_rDelegator.endObject(); + } + + private: + IMigrationProgress& m_rDelegator; + ::rtl::OUString m_sObjectName; + ::rtl::OUString m_sAction; + }; + + //==================================================================== + //= PhaseGuard + //==================================================================== + class PhaseGuard + { + public: + PhaseGuard( ProgressMixer& _rMixer ) + :m_rMixer( _rMixer ) + { + } + + PhaseGuard( ProgressMixer& _rMixer, const PhaseID _nID, const sal_uInt32 _nPhaseRange ) + :m_rMixer( _rMixer ) + { + start( _nID, _nPhaseRange ); + } + + ~PhaseGuard() + { + m_rMixer.endPhase(); + } + + void start( const PhaseID _nID, const sal_uInt32 _nPhaseRange ) + { + m_rMixer.startPhase( _nID, _nPhaseRange ); + } + + private: + ProgressMixer& m_rMixer; + }; + + //==================================================================== //= MigrationEngine_Impl - declaration //==================================================================== class MigrationEngine_Impl @@ -132,8 +829,10 @@ namespace dbmm private: ::comphelper::ComponentContext m_aContext; const Reference< XOfficeDatabaseDocument > m_xDocument; + const Reference< XModel > m_xDocumentModel; IMigrationProgress& m_rProgress; MigrationLog& m_rLogger; + mutable DocumentID m_nCurrentDocumentID; SubDocuments m_aSubDocs; size_t m_nFormCount; size_t m_nReportCount; @@ -146,14 +845,79 @@ namespace dbmm */ bool impl_collectSubDocuments_nothrow(); - /** reports the given error (usually an exception caught on the caller's side) - to the user, using the document's interaction handler, if any. - */ - void impl_reportError_nothrow( const Any& _rError ) const; - /** migrates the macros/scripts of the given sub document */ bool impl_handleDocument_nothrow( const SubDocument& _rDocument ) const; + + /** checks the structure of the 'Scripts' folder of a sub document + for unknown elements + + @return + <TRUE/> if and only if the 'Scripts' folder contains known elements only. + */ + bool impl_checkScriptStorageStructure_nothrow( const SubDocument& _rDocument ) const; + + /** migrates the scripts of the given "storage-based" script type + */ + bool impl_migrateScriptStorage_nothrow( + const SubDocument& _rDocument, + const ScriptType _eScriptType, + ProgressMixer& _rProgress, + const PhaseID _nPhaseID + ) const; + + /** migrates the content of the given "container based" libraries (Basic/Dialogs) + */ + bool impl_migrateContainerLibraries_nothrow( + const SubDocument& _rDocument, + const ScriptType _eScriptType, + ProgressMixer& _rProgress, + const PhaseID _nPhaseID + ) const; + + /** adjust the document-events which refer to macros/scripts in the document, taking into + account the new names of the moved libraries + */ + bool impl_adjustDocumentEvents_nothrow( + const SubDocument& _rDocument + ) const; + + /** adjusts the script references bound to form component events + */ + bool impl_adjustFormComponentEvents_nothrow( + const SubDocument& _rDocument + ) const; + + /** adjusts the script references for the elements of the given form component container + */ + void impl_adjustFormComponentEvents_throw( + const Reference< XIndexAccess >& _rxComponentContainer + ) const; + + /** adjusts the library name in the given script URL, so that it reflects + the new name of the library + + @return <TRUE/> + if and only if adjustments to the script code have been made + */ + bool impl_adjustScriptLibrary_nothrow( + const ::rtl::OUString& _rScriptType, + ::rtl::OUString& _inout_rScriptCode + ) const; + + bool impl_adjustScriptLibrary_nothrow( Any& _inout_rScriptDescriptor ) const; + bool impl_adjustScriptLibrary_nothrow( ScriptEventDescriptor& _inout_rScriptEvent ) const; + + /** asks the user for a password for the given library, and unprotects the library + + @return <TRUE/> + if and only if the library could be successfully unprotected + */ + bool impl_unprotectPasswordLibrary_throw( + const Reference< XLibraryContainerPassword >& _rxPasswordManager, + const ScriptType _eScriptType, + const ::rtl::OUString& _rLibraryName + ) const; }; //==================================================================== @@ -164,8 +928,10 @@ namespace dbmm const Reference< XOfficeDatabaseDocument >& _rxDocument, IMigrationProgress& _rProgress, MigrationLog& _rLogger ) :m_aContext( _rContext ) ,m_xDocument( _rxDocument ) + ,m_xDocumentModel( _rxDocument, UNO_QUERY_THROW ) ,m_rProgress( _rProgress ) ,m_rLogger( _rLogger ) + ,m_nCurrentDocumentID( - 1 ) ,m_aSubDocs() ,m_nFormCount( 0 ) ,m_nReportCount( 0 ) @@ -215,6 +981,14 @@ namespace dbmm m_rProgress.setOverallProgressValue( nOverallProgressValue ); } + // commit the root storage of the database document, for all changes made so far to take effect + if ( !lcl_commitDocumentStorage_nothrow( m_xDocumentModel, m_rLogger ) ) + return false; + + // save the document + if ( !lcl_storeDocument_nothrow( m_xDocumentModel, m_rLogger ) ) + return false; + return true; } @@ -263,141 +1037,744 @@ namespace dbmm //-------------------------------------------------------------------- bool MigrationEngine_Impl::impl_collectSubDocuments_nothrow() { + OSL_PRECOND( m_xDocument.is(), "MigrationEngine_Impl::impl_collectSubDocuments_nothrow: invalid document!" ); + if ( !m_xDocument.is() ) + return false; + try { - ::rtl::OUString sRootLocation; - - Reference< XFormDocumentsSupplier > xSuppForms( m_xDocument, UNO_QUERY_THROW ); - Reference< XNameAccess > xDocContainer( xSuppForms->getFormDocuments(), UNO_SET_THROW ); - m_nFormCount = lcl_collectHierarchicalElementNames_throw( xDocContainer, sRootLocation, m_aSubDocs, eForm ); + Reference< XNameAccess > xDocContainer( m_xDocument->getFormDocuments(), UNO_SET_THROW ); + m_nFormCount = lcl_collectHierarchicalElementNames_throw( xDocContainer, ::rtl::OUString(), m_aSubDocs, eForm ); - Reference< XReportDocumentsSupplier > xSuppReports( m_xDocument, UNO_QUERY_THROW ); - xDocContainer.set( xSuppReports->getReportDocuments(), UNO_SET_THROW ); - m_nReportCount = lcl_collectHierarchicalElementNames_throw( xDocContainer, sRootLocation, m_aSubDocs, eReport ); + xDocContainer.set( m_xDocument->getReportDocuments(), UNO_SET_THROW ); + m_nReportCount = lcl_collectHierarchicalElementNames_throw( xDocContainer, ::rtl::OUString(), m_aSubDocs, eReport ); } catch( const Exception& ) { - // TODO: check whether we can handle this error - DBG_UNHANDLED_EXCEPTION(); + m_rLogger.logFailure( MigrationError( + ERR_COLLECTING_DOCUMENTS_FAILED, + ::cppu::getCaughtException() + ) ); return false; } - return true; } //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_handleDocument_nothrow( const SubDocument& _rDocument ) const + { + OSL_ENSURE( m_nCurrentDocumentID == -1, + "MigrationEngine_Impl::impl_handleDocument_nothrow: there already is a current document!"); + m_nCurrentDocumentID = m_rLogger.startedDocument( _rDocument.eType, _rDocument.sHierarchicalName ); + + // start the progress + ::rtl::OUString sObjectName( lcl_getSubDocumentDescription( _rDocument ) ); + m_rProgress.startObject( sObjectName, ::rtl::OUString(), DEFAULT_DOC_PROGRESS_RANGE ); + + // ----------------- + // load the document + ::rtl::Reference< ProgressCapture > pStatusIndicator( new ProgressCapture( sObjectName, m_rProgress ) ); + SubDocument aSubDocument( _rDocument ); + if ( !lcl_loadSubDocument_nothrow( aSubDocument, pStatusIndicator.get(), m_rLogger ) ) + { + pStatusIndicator->dispose(); + m_rProgress.endObject(); + m_rLogger.finishedDocument( m_nCurrentDocumentID ); + m_nCurrentDocumentID = -1; + return false; + } + + // ----------------- + // migrate the libraries + ProgressDelegator aDelegator( m_rProgress, sObjectName, String( MacroMigrationResId( STR_MIGRATING_LIBS ) ) ); + ProgressMixer aProgressMixer( aDelegator ); + aProgressMixer.registerPhase( PHASE_JAVASCRIPT, 1 ); + aProgressMixer.registerPhase( PHASE_BEANSHELL, 1 ); + aProgressMixer.registerPhase( PHASE_PYTHON, 1 ); + aProgressMixer.registerPhase( PHASE_JAVA, 1 ); + aProgressMixer.registerPhase( PHASE_BASIC, 5 ); + // more weight than then others, assuming that usually, there are much more Basic macros than any other scripts + aProgressMixer.registerPhase( PHASE_DIALOGS, 1 ); + + bool bSuccess = impl_checkScriptStorageStructure_nothrow( aSubDocument ); + + // migrate storage-based script libraries (which can be handled by mere storage operations) + bSuccess = bSuccess + && impl_migrateScriptStorage_nothrow( aSubDocument, eJavaScript, aProgressMixer, PHASE_JAVASCRIPT ) + && impl_migrateScriptStorage_nothrow( aSubDocument, eBeanShell, aProgressMixer, PHASE_BEANSHELL ) + && impl_migrateScriptStorage_nothrow( aSubDocument, ePython, aProgressMixer, PHASE_PYTHON ) + && impl_migrateScriptStorage_nothrow( aSubDocument, eJava, aProgressMixer, PHASE_JAVA ); + + // migrate Basic and dialog libraries + bSuccess = bSuccess + && impl_migrateContainerLibraries_nothrow( aSubDocument, eBasic, aProgressMixer, PHASE_BASIC ) + && impl_migrateContainerLibraries_nothrow( aSubDocument, eDialog, aProgressMixer, PHASE_DIALOGS ); + + // adjust the events in the document + // (note that errors are ignored here - failure to convert a script reference + // is not considered a critical error) + if ( bSuccess ) + { + impl_adjustDocumentEvents_nothrow( aSubDocument ); + impl_adjustFormComponentEvents_nothrow( aSubDocument ); + } + + // ----------------- + // clean up + // store the sub document, including removal of the (now obsolete) "Scripts" sub folder + bSuccess = bSuccess + && ScriptsStorage::removeFromDocument( aSubDocument.xDocument, m_rLogger ) + && lcl_commitDocumentStorage_nothrow( aSubDocument.xDocument, m_rLogger ) + && lcl_storeEmbeddedDocument_nothrow( aSubDocument ); + + // unload in any case, even if we were not successful + bSuccess = lcl_unloadSubDocument_nothrow( aSubDocument, m_rLogger ) + && bSuccess; + + pStatusIndicator->dispose(); + + // end the progress, just in case the ProgressCapture didn't receive the XStatusIndicator::end event + m_rProgress.endObject(); + + m_rLogger.finishedDocument( m_nCurrentDocumentID ); + m_nCurrentDocumentID = -1; + return bSuccess; + } + + //-------------------------------------------------------------------- namespace { - //................................................................ - static void lcl_disposeComponent_nothrow( const Reference< XCommandProcessor >& _rxCommandProc ) + static ::rtl::OUString lcl_createTargetLibName( const SubDocument& _rDocument, + const ::rtl::OUString& _rSourceLibName, const Reference< XNameAccess >& _rxTargetStorage ) { - OSL_PRECOND( _rxCommandProc.is(), "lcl_disposeComponent_nothrow: illegal object!" ); - if ( !_rxCommandProc.is() ) - return; + // a prefix denoting the type + const ::rtl::OUString sPrefix( ::rtl::OUString::createFromAscii( _rDocument.eType == eForm ? "Form_" : "Report_" ) ); - bool bCouldClose = false; - try + ::rtl::OUStringBuffer aBuffer; + aBuffer.append( sPrefix ); + + // first try with the base name of the sub document + aBuffer.append( _rDocument.sHierarchicalName.copy( + _rDocument.sHierarchicalName.lastIndexOf( '/' ) + 1 ) ); + aBuffer.appendAscii( "_" ); + aBuffer.append( _rSourceLibName ); + ::rtl::OUString sTargetName( aBuffer.makeStringAndClear() ); + if ( !_rxTargetStorage->hasByName( sTargetName ) ) + return sTargetName; + + // if this name is already used (which is valid, since documents with the same base + // name can exist in different logical folders), then use the complete name + aBuffer.append( sPrefix ); + aBuffer.append( ::comphelper::string::searchAndReplaceAllAsciiWithAscii( + _rDocument.sHierarchicalName, "/", "_" ) ); + aBuffer.appendAscii( "_" ); + aBuffer.append( _rSourceLibName ); + return aBuffer.makeStringAndClear(); + + } + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_checkScriptStorageStructure_nothrow( const SubDocument& _rDocument ) const + { + OSL_PRECOND( _rDocument.xDocument.is(), "MigrationEngine_Impl::impl_checkScriptStorageStructure_nothrow: invalid document!" ); + if ( !_rDocument.xDocument.is() ) + return false; + + try + { + // the root storage of the document whose scripts are to be migrated + ScriptsStorage aDocStorage( _rDocument.xDocument, m_rLogger ); + if ( !aDocStorage.isValid() ) + { // no scripts at all, or no scripts of the given type + return !m_rLogger.hadFailure(); + } + ::std::set< ::rtl::OUString > aElementNames( aDocStorage.getElementNames() ); + + ScriptType aKnownStorageBasedTypes[] = { + eBeanShell, eJavaScript, ePython, eJava + }; + for ( size_t i=0; i<sizeof( aKnownStorageBasedTypes ) / sizeof( aKnownStorageBasedTypes[0] ); ++i ) + aElementNames.erase( lcl_getScriptsSubStorageName( aKnownStorageBasedTypes[i] ) ); + + if ( !aElementNames.empty() ) { - Command aCommand; - aCommand.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "shutdown" ) ); - OSL_VERIFY( _rxCommandProc->execute( - aCommand, _rxCommandProc->createCommandIdentifier(), NULL ) >>= bCouldClose ); + m_rLogger.logFailure( MigrationError( + ERR_UNKNOWN_SCRIPT_FOLDER, + lcl_getSubDocumentDescription( _rDocument ), + *aElementNames.begin() + ) ); + return false; } - catch( const Exception& ) + } + catch( const Exception& ) + { + m_rLogger.logFailure( MigrationError( + ERR_EXAMINING_SCRIPTS_FOLDER_FAILED, + lcl_getSubDocumentDescription( _rDocument ), + ::cppu::getCaughtException() + ) ); + return false; + } + return true; + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_migrateScriptStorage_nothrow( const SubDocument& _rDocument, + const ScriptType _eScriptType, ProgressMixer& _rProgress, const PhaseID _nPhaseID ) const + { + OSL_PRECOND( _rDocument.xDocument.is(), "MigrationEngine_Impl::impl_migrateScriptStorage_nothrow: invalid document!" ); + if ( !_rDocument.xDocument.is() ) + return false; + + ScriptsStorage aDatabaseScripts( m_rLogger ); + // the scripts of our complete database document - created on demand only + SharedStorage xTargetStorage; + // the target for moving the scripts storages - created on demand only + + PhaseGuard aPhase( _rProgress ); + bool bSuccess = false; + Any aException; + try + { + // the root storage of the document whose scripts are to be migrated + ScriptsStorage aDocStorage( _rDocument.xDocument, m_rLogger ); + if ( !aDocStorage.isValid() + || !aDocStorage.hasScripts( _eScriptType ) + ) { - DBG_UNHANDLED_EXCEPTION(); + // no scripts at all, or no scripts of the given type + _rProgress.startPhase( _nPhaseID, 1 ); + _rProgress.endPhase(); + return !m_rLogger.hadFailure(); } - if ( !bCouldClose ) + + SharedStorage xScriptsRoot( aDocStorage.getScriptsRoot( _eScriptType ) ); + if ( !xScriptsRoot.is() ) + throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "internal error" ) ), NULL ); + + // loop through the script libraries + Sequence< ::rtl::OUString > aStorageElements( xScriptsRoot->getElementNames() ); + aPhase.start( _nPhaseID, aStorageElements.getLength() ); + + for ( const ::rtl::OUString* element = aStorageElements.getConstArray(); + element != aStorageElements.getConstArray() + aStorageElements.getLength(); + ++element + ) { - ; - // TODO: can we handle this somehow? + bool bIsScriptLibrary = xScriptsRoot->isStorageElement( *element ); + OSL_ENSURE( bIsScriptLibrary, + "MigrationEngine_Impl::impl_migrateScriptStorage_nothrow: warning: unknown scripts storage structure!" ); + // we cannot handle this. We would need to copy this stream to the respective scripts storage + // of the database document, but we cannot guarantee that the name is not used, yet, and we cannot + // simply rename the thing. + if ( !bIsScriptLibrary ) + { + m_rLogger.logFailure( MigrationError( + ERR_UNEXPECTED_LIBSTORAGE_ELEMENT, + lcl_getSubDocumentDescription( _rDocument ), + getScriptTypeDisplayName( _eScriptType ), + *element + ) ); + return false; + } + + // ensure we have access to the DBDoc's scripts storage + if ( !aDatabaseScripts.isValid() ) + { // not needed 'til now + aDatabaseScripts.bind( m_xDocumentModel ); + if ( aDatabaseScripts.isValid() ) + xTargetStorage = aDatabaseScripts.getScriptsRoot( _eScriptType ); + + if ( !xTargetStorage.is() ) + { + m_rLogger.logFailure( MigrationError( + ERR_CREATING_DBDOC_SCRIPT_STORAGE_FAILED, + getScriptTypeDisplayName( _eScriptType ) + ) ); + return false; + } + } + + // move the library to the DBDoc's scripts library, under the new name + ::rtl::OUString sNewLibName( lcl_createTargetLibName( _rDocument, *element, xTargetStorage.getTyped().get() ) ); + xScriptsRoot->moveElementTo( *element, xTargetStorage, sNewLibName ); + + // log the fact that we moved the library + m_rLogger.movedLibrary( m_nCurrentDocumentID, _eScriptType, *element, sNewLibName ); + + // progress + _rProgress.advancePhase( element - aStorageElements.getConstArray() ); } + + // commit the storages, so the changes we made persist + if ( !lcl_commitStorage_nothrow( xScriptsRoot ) + || ( xTargetStorage.is() && !lcl_commitStorage_nothrow( xTargetStorage ) ) + ) + { + m_rLogger.logFailure( MigrationError( + ERR_COMMITTING_SCRIPT_STORAGES_FAILED, + lcl_getSubDocumentDescription( _rDocument ), + getScriptTypeDisplayName( _eScriptType ) + ) ); + return false; + } + + // now that the concrete scripts storage does not have any elements anymore, + // remove it + xScriptsRoot.reset( NULL ); // need to reset the storage to be allowed to remove it + aDocStorage.removeScriptTypeStorage( _eScriptType ); + + // done so far + bSuccess = aDocStorage.commit() + && aDatabaseScripts.commit(); + } + catch( const Exception& ) + { + aException = ::cppu::getCaughtException(); + bSuccess = false; } - //................................................................ - static Reference< XModel > lcl_loadSubDocument_nothrow( const SubDocument& _rDocument, - const Reference< XStatusIndicator >& _rxProgress ) + // log the error, if any + if ( !bSuccess ) { - Reference< XModel > xDocument; + m_rLogger.logFailure( MigrationError( + ERR_GENERAL_SCRIPT_MIGRATION_FAILURE, + lcl_getSubDocumentDescription( _rDocument ), + getScriptTypeDisplayName( _eScriptType ), + aException + ) ); + } - try + return bSuccess; + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow( const SubDocument& _rDocument, + const ScriptType _eScriptType, ProgressMixer& _rProgress, const PhaseID _nPhaseID ) const + { + OSL_PRECOND( ( _eScriptType == eBasic ) || ( _eScriptType == eDialog ), + "MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow: illegal script type!" ); + + bool bSuccess = false; + PhaseGuard aPhase( _rProgress ); + Any aException; + do // artificial loop for flow control only + { + try + { + // access library container of the sub document + Reference< XEmbeddedScripts > xSubDocScripts( _rDocument.xDocument, UNO_QUERY ); + if ( !xSubDocScripts.is() ) + { // no script support in the sub document -> nothing to migrate + // (though ... this is suspicious, at least ...) + bSuccess = true; + break; + } + + Reference< XStorageBasedLibraryContainer > xSourceLibraries( + _eScriptType == eBasic ? xSubDocScripts->getBasicLibraries() : xSubDocScripts->getDialogLibraries(), + UNO_QUERY_THROW + ); + Reference< XLibraryContainerPassword > xSourcePasswords( xSourceLibraries, UNO_QUERY ); + OSL_ENSURE( xSourcePasswords.is(), + "MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow: suspicious: no password management for the source libraries!" ); + + Sequence< ::rtl::OUString > aSourceLibNames( xSourceLibraries->getElementNames() ); + aPhase.start( _nPhaseID, aSourceLibNames.getLength() ); + + if ( !xSourceLibraries->hasElements() ) { - ::comphelper::NamedValueCollection aLoadArgs; - aLoadArgs.put( "Hidden", (sal_Bool)sal_True ); - aLoadArgs.put( "StatusIndicator", _rxProgress ); + bSuccess = true; + break; + } - Reference< XCommandProcessor > xCommandProcessor( _rDocument.xCommandProcessor, UNO_SET_THROW ); - Command aCommand; - aCommand.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "openDesign" ) ); - aCommand.Argument <<= aLoadArgs.getPropertyValues(); - Reference< XComponent > xDocComponent( - xCommandProcessor->execute( - aCommand, xCommandProcessor->createCommandIdentifier(), NULL - ), - UNO_QUERY - ); - OSL_ENSURE( xDocComponent.is(), "lcl_loadSubDocument_nothrow: no component loaded!" ); + // create library containers for the document - those will be the target for the migration + Reference< XStorageBasedDocument > xStorageDoc( m_xDocument, UNO_QUERY_THROW ); + Reference< XStorageBasedLibraryContainer > xTargetLibraries; + if ( _eScriptType == eBasic ) + { + xTargetLibraries.set( DocumentScriptLibraryContainer::create( + m_aContext.getUNOContext(), xStorageDoc ), UNO_QUERY_THROW ); + } + else + { + xTargetLibraries.set( DocumentDialogLibraryContainer::create( + m_aContext.getUNOContext(), xStorageDoc ), UNO_QUERY_THROW ); + } + + // copy all libs to the target, with potentially renaming them + const ::rtl::OUString* pSourceLibBegin = aSourceLibNames.getConstArray(); + const ::rtl::OUString* pSourceLibEnd = pSourceLibBegin + aSourceLibNames.getLength(); + for ( const ::rtl::OUString* pSourceLibName = pSourceLibBegin; + pSourceLibName != pSourceLibEnd; + ++pSourceLibName + ) + { + // if the library is password-protected, ask the user to unprotect it + if ( xSourcePasswords.is() + && xSourcePasswords->isLibraryPasswordProtected( *pSourceLibName ) + && !xSourcePasswords->isLibraryPasswordVerified( *pSourceLibName ) + ) + { + if ( !impl_unprotectPasswordLibrary_throw( xSourcePasswords, _eScriptType, *pSourceLibName ) ) + { + m_rLogger.logFailure( MigrationError( + ERR_PASSWORD_VERIFICATION_FAILED, + _rDocument.sHierarchicalName, + getScriptTypeDisplayName( _eScriptType ), + *pSourceLibName + ) ); + return false; + } + } + + ::rtl::OUString sNewLibName( lcl_createTargetLibName( _rDocument, *pSourceLibName, xTargetLibraries.get() ) ); + + if ( xSourceLibraries->isLibraryLink( *pSourceLibName ) ) + { + // just re-create the link in the target library + xTargetLibraries->createLibraryLink( + sNewLibName, + xSourceLibraries->getLibraryLinkURL( *pSourceLibName ), + xSourceLibraries->isLibraryReadOnly( *pSourceLibName ) + ); + } + else + { + if ( !xSourceLibraries->isLibraryLoaded( *pSourceLibName ) ) + xSourceLibraries->loadLibrary( *pSourceLibName ); + + // copy the content of this particular libary + Reference< XNameAccess > xSourceLib( xSourceLibraries->getByName( *pSourceLibName ), UNO_QUERY_THROW ); + Reference< XNameContainer > xTargetLib( xTargetLibraries->createLibrary( sNewLibName ), UNO_QUERY_THROW ); + + Sequence< ::rtl::OUString > aLibElementNames( xSourceLib->getElementNames() ); + for ( const ::rtl::OUString* pSourceElementName = aLibElementNames.getConstArray(); + pSourceElementName != aLibElementNames.getConstArray() + aLibElementNames.getLength(); + ++pSourceElementName + ) + { + Any aElement = xSourceLib->getByName( *pSourceElementName ); + OSL_ENSURE( aElement.hasValue(), + "MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow: invalid (empty) lib element!" ); + xTargetLib->insertByName( *pSourceElementName, aElement ); + } + + // transfer the read-only flag + xTargetLibraries->setLibraryReadOnly( + sNewLibName, xSourceLibraries->isLibraryReadOnly( *pSourceLibName ) ); + } - xDocument.set( xDocComponent, UNO_QUERY_THROW ); + // remove the source lib + xSourceLibraries->removeLibrary( *pSourceLibName ); + + // tell the logger + m_rLogger.movedLibrary( m_nCurrentDocumentID, _eScriptType, *pSourceLibName, sNewLibName ); + + // tell the progress + _rProgress.advancePhase( pSourceLibName - pSourceLibBegin ); } - catch( const Exception& ) + + // clean up + xSourceLibraries->storeLibraries(); + + xTargetLibraries->storeLibraries(); + Reference< XStorage > xTargetRoot( xTargetLibraries->getRootLocation(), UNO_QUERY_THROW ); + bSuccess = lcl_commitStorage_nothrow( xTargetRoot ); + } + catch( const Exception& ) + { + aException = ::cppu::getCaughtException(); + bSuccess = false; + } + } while ( false ); + + // log the error, if any + if ( !bSuccess ) + { + m_rLogger.logFailure( MigrationError( + ERR_GENERAL_MACRO_MIGRATION_FAILURE, + lcl_getSubDocumentDescription( _rDocument ), + aException + ) ); + } + + return bSuccess; + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow( const ::rtl::OUString& _rScriptType, + ::rtl::OUString& _inout_rScriptCode ) const + { + OSL_PRECOND( _inout_rScriptCode.getLength(), "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: invalid script!" ); + if ( !_inout_rScriptCode.getLength() ) + return false; + + bool bSuccess = false; + Any aException; + try + { + if ( !_rScriptType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Script" ) ) + || !_rScriptType.getLength() + ) { - // TODO: how to proceed? - DBG_UNHANDLED_EXCEPTION(); + OSL_ENSURE( false, + "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: no or unknown script type!" ); + m_rLogger.logRecoverable( MigrationError( + ERR_UNKNOWN_SCRIPT_TYPE, + _rScriptType + ) ); + return false; + } + + // analyze the script URI + Reference< XUriReferenceFactory > xUriRefFac = UriReferenceFactory::create( m_aContext.getUNOContext() ); + Reference< XVndSunStarScriptUrlReference > xUri( xUriRefFac->parse( _inout_rScriptCode ), UNO_QUERY_THROW ); + + ::rtl::OUString sScriptLanguage = xUri->getParameter( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "language" ) ) ); + ScriptType eScriptType = eBasic; + if ( !lcl_getScriptTypeFromLanguage( sScriptLanguage, eScriptType ) ) + { + OSL_ENSURE( false, + "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: unknown script language!" ); + m_rLogger.logRecoverable( MigrationError( + ERR_UNKNOWN_SCRIPT_LANGUAGE, + sScriptLanguage + ) ); + return false; + } + + ::rtl::OUString sLocation = xUri->getParameter( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "location" ) ) ); + if ( !sLocation.equalsAscii( "document" ) ) + { + // only document libraries must be migrated, of course + return false; + } + + ::rtl::OUString sScriptName = xUri->getName(); + sal_Int32 nLibModuleSeparator = sScriptName.indexOf( '.' ); + if ( nLibModuleSeparator < 0 ) + { + OSL_ENSURE( false, + "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: invalid/unknown location format!" ); + m_rLogger.logRecoverable( MigrationError( + ERR_UNKNOWN_SCRIPT_NAME_FORMAT, + sScriptName + ) ); + return false; } - return xDocument; + // replace the library name + ::rtl::OUString sLibrary = sScriptName.copy( 0, nLibModuleSeparator ); + ::rtl::OUString sNewLibName = m_rLogger.getNewLibraryName( + m_nCurrentDocumentID, eScriptType, sLibrary ); + OSL_ENSURE( sLibrary != sNewLibName, + "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: a library which has not been migrated?" ); + + ::rtl::OUStringBuffer aNewLocation; + aNewLocation.append( sNewLibName ); + aNewLocation.append( sScriptName.copy( nLibModuleSeparator ) ); + xUri->setName( aNewLocation.makeStringAndClear() ); + + // update the new script URL + _inout_rScriptCode = xUri->getUriReference(); + bSuccess = true; + } + catch( const Exception& ) + { + aException = ::cppu::getCaughtException(); + bSuccess = false; } + + // log the failure, if any + if ( !bSuccess ) + { + m_rLogger.logRecoverable( MigrationError( + ERR_SCRIPT_TRANSLATION_FAILURE, + _rScriptType, + _inout_rScriptCode, + aException + ) ); + } + + return bSuccess; } //-------------------------------------------------------------------- - bool MigrationEngine_Impl::impl_handleDocument_nothrow( const SubDocument& _rDocument ) const + bool MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow( ScriptEventDescriptor& _inout_rScriptEvent ) const { - DocumentID nDocID = m_rLogger.startedDocument( _rDocument.eType, _rDocument.sHierarchicalName ); + if ( _inout_rScriptEvent.ScriptType.getLength() && _inout_rScriptEvent.ScriptCode.getLength() ) + return impl_adjustScriptLibrary_nothrow( _inout_rScriptEvent.ScriptType, _inout_rScriptEvent.ScriptCode ); + return false; + } - // start the progress - ::rtl::OUString aProgress; - aProgress = String( MacroMigrationResId( _rDocument.eType == eForm ? STR_FORM : STR_REPORT ) ); - ::comphelper::string::searchAndReplaceAsciiI( aProgress, "$name$", _rDocument.sHierarchicalName ); - m_rProgress.startObject( aProgress, ::rtl::OUString(), DEFAULT_DOC_PROGRESS_RANGE ); + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow( Any& _inout_rScriptDescriptor ) const + { + ::comphelper::NamedValueCollection aScriptDesc( _inout_rScriptDescriptor ); - // load the document - ::rtl::Reference< ProgressCapture > pStatusIndicator( new ProgressCapture( aProgress, m_rProgress ) ); - Reference< XModel > xDocument( lcl_loadSubDocument_nothrow( _rDocument, pStatusIndicator.get() ) ); - if ( !xDocument.is() ) + ::rtl::OUString sScriptType; + ::rtl::OUString sScript; + try { - pStatusIndicator->dispose(); - m_rProgress.endObject(); - m_rLogger.finishedDocument( nDocID, false ); - // TODO: log the *reason* for the failure + OSL_VERIFY( aScriptDesc.get_ensureType( "EventType", sScriptType ) ); + OSL_VERIFY( aScriptDesc.get_ensureType( "Script", sScript ) ); + } + catch( const Exception& ) + { + m_rLogger.logRecoverable( MigrationError( + ERR_INVALID_SCRIPT_DESCRIPTOR_FORMAT, + ::cppu::getCaughtException() + ) ); + } + + if ( sScriptType.getLength() && sScript.getLength() ) + if ( !impl_adjustScriptLibrary_nothrow( sScriptType, sScript ) ) + return false; + + aScriptDesc.put( "Script", sScript ); + _inout_rScriptDescriptor <<= aScriptDesc.getPropertyValues(); + return true; + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_adjustDocumentEvents_nothrow( const SubDocument& _rDocument ) const + { + try + { + Reference< XEventsSupplier > xSuppEvents( _rDocument.xDocument, UNO_QUERY ); + if ( !xSuppEvents.is() ) + // this is allowed. E.g. new-style reports currently do not support this + return true; + + Reference< XNameReplace > xEvents( xSuppEvents->getEvents(), UNO_SET_THROW ); + Sequence< ::rtl::OUString > aEventNames = xEvents->getElementNames(); + + Any aEvent; + for ( const ::rtl::OUString* eventName = aEventNames.getConstArray(); + eventName != aEventNames.getConstArray() + aEventNames.getLength(); + ++eventName + ) + { + aEvent = xEvents->getByName( *eventName ); + if ( !aEvent.hasValue() ) + continue; + + // translate + if ( !impl_adjustScriptLibrary_nothrow( aEvent ) ) + continue; + + // put back + xEvents->replaceByName( *eventName, aEvent ); + } + } + catch( const Exception& ) + { + m_rLogger.logRecoverable( MigrationError( + ERR_ADJUSTING_DOCUMENT_EVENTS_FAILED, + lcl_getSubDocumentDescription( _rDocument ), + ::cppu::getCaughtException() + ) ); return false; } + return true; + } - // TODO + //-------------------------------------------------------------------- + void MigrationEngine_Impl::impl_adjustFormComponentEvents_throw( const Reference< XIndexAccess >& _rxComponentContainer ) const + { + FormComponentIterator aCompIter( _rxComponentContainer ); + while ( aCompIter.hasMore() ) + { + // 1. adjust the component's scripts of the current component + FormComponentScripts aComponent( aCompIter.next() ); + Sequence< ScriptEventDescriptor > aEvents( aComponent.getEvents() ); - // clean up - lcl_disposeComponent_nothrow( _rDocument.xCommandProcessor ); - pStatusIndicator->dispose(); + bool bChangedComponentEvents = false; + for ( ScriptEventDescriptor* scriptEvent = aEvents.getArray(); + scriptEvent != aEvents.getArray() + aEvents.getLength(); + ++scriptEvent + ) + { + if ( !impl_adjustScriptLibrary_nothrow( *scriptEvent ) ) + continue; - // end the progress, just in case the ProgressCapture didn't receive the XStatusIndicator::end event - m_rProgress.endObject(); + bChangedComponentEvents = true; + } + + if ( bChangedComponentEvents ) + aComponent.setEvents( aEvents ); - m_rLogger.finishedDocument( nDocID, true ); + // 2. step down if the component is a container itself + Reference< XIndexAccess > xContainer( aComponent.getComponent(), UNO_QUERY ); + if ( xContainer.is() ) + impl_adjustFormComponentEvents_throw( xContainer ); + } + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_adjustFormComponentEvents_nothrow( const SubDocument& _rDocument ) const + { + try + { + DrawPageIterator aPageIter( _rDocument.xDocument ); + while ( aPageIter.hasMore() ) + { + Reference< XFormsSupplier > xSuppForms( aPageIter.next(), UNO_QUERY_THROW ); + Reference< XIndexAccess > xForms( xSuppForms->getForms(), UNO_QUERY_THROW ); + impl_adjustFormComponentEvents_throw( xForms ); + } + } + catch( const Exception& ) + { + m_rLogger.logRecoverable( MigrationError( + ERR_ADJUSTING_FORMCOMP_EVENTS_FAILED, + lcl_getSubDocumentDescription( _rDocument ), + ::cppu::getCaughtException() + ) ); + return false; + } return true; } //-------------------------------------------------------------------- - void MigrationEngine_Impl::impl_reportError_nothrow( const Any& _rError ) const + bool MigrationEngine_Impl::impl_unprotectPasswordLibrary_throw( const Reference< XLibraryContainerPassword >& _rxPasswordManager, + const ScriptType _eScriptType, const ::rtl::OUString& _rLibraryName ) const { - DocumentErrorHandling::reportError( m_aContext, m_xDocument, _rError ); + // a human-readable description of the affected library + ::rtl::OUString sLibraryDescription( String( + MacroMigrationResId( STR_LIBRARY_TYPE_AND_NAME ) ) ); + ::comphelper::string::searchAndReplaceAsciiI( sLibraryDescription, "$type$", + getScriptTypeDisplayName( _eScriptType ) ); + ::comphelper::string::searchAndReplaceAsciiI( sLibraryDescription, "$library$", + _rLibraryName ); + + InteractionHandler aHandler( m_aContext, m_xDocumentModel ); + ::rtl::OUString sPassword; + while ( true ) + { + if ( !aHandler.requestDocumentPassword( sLibraryDescription, sPassword ) ) + // aborted by the user + return false; + + bool bSuccessVerification = _rxPasswordManager->verifyLibraryPassword( _rLibraryName, sPassword ); + if ( bSuccessVerification ) + return true; + } + + return false; } //==================================================================== //= MigrationEngine //==================================================================== //-------------------------------------------------------------------- - MigrationEngine::MigrationEngine( const ::comphelper::ComponentContext& _rContext, const Reference< XOfficeDatabaseDocument >& _rxDocument, - IMigrationProgress& _rProgress, MigrationLog& _rLogger ) + MigrationEngine::MigrationEngine( const ::comphelper::ComponentContext& _rContext, + const Reference< XOfficeDatabaseDocument >& _rxDocument, IMigrationProgress& _rProgress, + MigrationLog& _rLogger ) :m_pImpl( new MigrationEngine_Impl( _rContext, _rxDocument, _rProgress, _rLogger ) ) { } diff --git a/dbaccess/source/ext/macromigration/migrationerror.hxx b/dbaccess/source/ext/macromigration/migrationerror.hxx new file mode 100644 index 000000000..a4e7e5334 --- /dev/null +++ b/dbaccess/source/ext/macromigration/migrationerror.hxx @@ -0,0 +1,162 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2008 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* $RCSfile: migrationerror.hxx,v $ +* +* $Revision: 1.1.2.3 $ +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +************************************************************************/ + +#ifndef DBACCESS_MIGRATIONERROR_HXX +#define DBACCESS_MIGRATIONERROR_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/uno/Any.hxx> +/** === end UNO includes === **/ + +#include <vector> + +//........................................................................ +namespace dbmm +{ +//........................................................................ + + enum MigrationErrorType + { + ERR_OPENING_SUB_DOCUMENT_FAILED = 1, + ERR_CLOSING_SUB_DOCUMENT_FAILED, + ERR_STORAGE_COMMIT_FAILED, + ERR_STORING_DATABASEDOC_FAILED, + ERR_COLLECTING_DOCUMENTS_FAILED, + ERR_UNEXPECTED_LIBSTORAGE_ELEMENT, + ERR_CREATING_DBDOC_SCRIPT_STORAGE_FAILED, + ERR_COMMITTING_SCRIPT_STORAGES_FAILED, + ERR_GENERAL_SCRIPT_MIGRATION_FAILURE, + ERR_GENERAL_MACRO_MIGRATION_FAILURE, + ERR_UNKNOWN_SCRIPT_TYPE, + ERR_UNKNOWN_SCRIPT_LANGUAGE, + ERR_UNKNOWN_SCRIPT_NAME_FORMAT, + ERR_SCRIPT_TRANSLATION_FAILURE, + ERR_INVALID_SCRIPT_DESCRIPTOR_FORMAT, + ERR_ADJUSTING_DOCUMENT_EVENTS_FAILED, + ERR_ADJUSTING_FORMCOMP_EVENTS_FAILED, + ERR_BIND_SCRIPT_STORAGE_FAILED, + ERR_REMOVE_SCRIPTS_STORAGE_FAILED, + ERR_DOCUMENT_BACKUP_FAILED, + ERR_UNKNOWN_SCRIPT_FOLDER, + ERR_EXAMINING_SCRIPTS_FOLDER_FAILED, + ERR_PASSWORD_VERIFICATION_FAILED + }; + + //==================================================================== + //= MigrationError + //==================================================================== + /** encapsulates information about an error which happened during the migration + */ + struct MigrationError + { + const MigrationErrorType eType; + ::std::vector< ::rtl::OUString > aErrorDetails; + const ::com::sun::star::uno::Any aCaughtException; + + MigrationError( + const MigrationErrorType _eType ) + :eType( _eType ) + { + } + + MigrationError( + const MigrationErrorType _eType, + const ::com::sun::star::uno::Any& _rCaughtException ) + :eType( _eType ) + ,aCaughtException( _rCaughtException ) + { + } + + MigrationError( + const MigrationErrorType _eType, + const ::rtl::OUString& _rDetail ) + :eType( _eType ) + { + impl_constructDetails( _rDetail ); + } + + MigrationError( + const MigrationErrorType _eType, + const ::rtl::OUString& _rDetail, + const ::com::sun::star::uno::Any& _rCaughtException ) + :eType( _eType ) + ,aCaughtException( _rCaughtException ) + { + impl_constructDetails( _rDetail ); + } + + MigrationError( + const MigrationErrorType _eType, + const ::rtl::OUString& _rDetail1, + const ::rtl::OUString& _rDetail2 ) + :eType( _eType ) + { + impl_constructDetails( _rDetail1, _rDetail2 ); + } + + MigrationError( + const MigrationErrorType _eType, + const ::rtl::OUString& _rDetail1, + const ::rtl::OUString& _rDetail2, + const ::com::sun::star::uno::Any& _rCaughtException ) + :eType( _eType ) + ,aCaughtException( _rCaughtException ) + { + impl_constructDetails( _rDetail1, _rDetail2 ); + } + + MigrationError( + const MigrationErrorType _eType, + const ::rtl::OUString& _rDetail1, + const ::rtl::OUString& _rDetail2, + const ::rtl::OUString& _rDetail3 ) + :eType( _eType ) + { + impl_constructDetails( _rDetail1, _rDetail2, _rDetail3 ); + } + + private: + void impl_constructDetails( + const ::rtl::OUString& _rDetail1, + const ::rtl::OUString& _rDetail2 = ::rtl::OUString(), + const ::rtl::OUString& _rDetail3 = ::rtl::OUString() + ) + { + if ( _rDetail1.getLength() ) aErrorDetails.push_back( _rDetail1 ); + if ( _rDetail2.getLength() ) aErrorDetails.push_back( _rDetail2 ); + if ( _rDetail3.getLength() ) aErrorDetails.push_back( _rDetail3 ); + } + }; + +//........................................................................ +} // namespace dbmm +//........................................................................ + +#endif // DBACCESS_MIGRATIONERROR_HXX + diff --git a/dbaccess/source/ext/macromigration/migrationlog.cxx b/dbaccess/source/ext/macromigration/migrationlog.cxx index 659383499..b15a6b5f9 100644 --- a/dbaccess/source/ext/macromigration/migrationlog.cxx +++ b/dbaccess/source/ext/macromigration/migrationlog.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: migrationlog.cxx,v $ - * $Revision: 1.4 $ + * $Revision: 1.4.2.8 $ * * This file is part of OpenOffice.org. * @@ -33,16 +33,20 @@ #include "dbmm_module.hxx" #include "dbmm_global.hrc" +#include "migrationerror.hxx" #include "migrationlog.hxx" /** === begin UNO includes === **/ /** === end UNO includes === **/ +#include <comphelper/anytostring.hxx> +#include <comphelper/string.hxx> #include <tools/string.hxx> #include <rtl/ustrbuf.hxx> #include <vector> #include <map> +#include <list> //........................................................................ namespace dbmm @@ -84,20 +88,17 @@ namespace dbmm SubDocumentType eType; ::rtl::OUString sName; ::std::vector< LibraryEntry > aMovedLibraries; - bool bSuccess; DocumentEntry() :eType( eForm ) ,sName() ,aMovedLibraries() - ,bSuccess( false ) { } DocumentEntry( const SubDocumentType _eType, const ::rtl::OUString& _rName ) :eType( _eType ) ,sName( _rName ) - ,bSuccess( false ) { } }; @@ -108,12 +109,19 @@ namespace dbmm typedef ::std::map< DocumentID, DocumentEntry > DocumentLogs; //==================================================================== + //= ErrorLog + //==================================================================== + typedef ::std::list< MigrationError > ErrorLog; + + //==================================================================== //= MigrationLog_Data //==================================================================== struct MigrationLog_Data { ::rtl::OUString sBackupLocation; DocumentLogs aDocumentLogs; + ErrorLog aFailures; + ErrorLog aWarnings; }; //==================================================================== @@ -131,6 +139,24 @@ namespace dbmm } //-------------------------------------------------------------------- + void MigrationLog::logFailure( const MigrationError& _rError ) + { + m_pData->aFailures.push_back( _rError ); + } + + //-------------------------------------------------------------------- + void MigrationLog::logRecoverable( const MigrationError& _rError ) + { + m_pData->aWarnings.push_back( _rError ); + } + + //-------------------------------------------------------------------- + bool MigrationLog::hadFailure() const + { + return !m_pData->aFailures.empty(); + } + + //-------------------------------------------------------------------- void MigrationLog::backedUpDocument( const ::rtl::OUString& _rNewDocumentLocation ) { m_pData->sBackupLocation = _rNewDocumentLocation; @@ -172,13 +198,14 @@ namespace dbmm } //-------------------------------------------------------------------- - void MigrationLog::finishedDocument( const DocumentID _nDocID, const bool _bSuccessful ) + void MigrationLog::finishedDocument( const DocumentID _nDocID ) { OSL_ENSURE( m_pData->aDocumentLogs.find( _nDocID ) != m_pData->aDocumentLogs.end(), "MigrationLog::finishedDocument: document is not known!" ); DocumentEntry& rDocEntry = m_pData->aDocumentLogs[ _nDocID ]; - rDocEntry.bSuccess = _bSuccessful; + (void)rDocEntry; + // nothing to do here } //-------------------------------------------------------------------- @@ -213,21 +240,180 @@ namespace dbmm //-------------------------------------------------------------------- namespace { - String lcl_getScriptTypeDisplayName( const ScriptType _eType ) + //---------------------------------------------------------------- + static void lcl_appendErrorDescription( ::rtl::OUStringBuffer& _inout_rBuffer, const MigrationError& _rError ) + { + const sal_Char* pAsciiErrorDescription( NULL ); + ::std::vector< const sal_Char* > aAsciiParameterNames; + switch ( _rError.eType ) + { + case ERR_OPENING_SUB_DOCUMENT_FAILED: + pAsciiErrorDescription = "opening '#name#' failed"; + aAsciiParameterNames.push_back( "#name#" ); + break; + + case ERR_CLOSING_SUB_DOCUMENT_FAILED: + pAsciiErrorDescription = "closing '#name#' failed"; + aAsciiParameterNames.push_back( "#name#" ); + break; + + case ERR_STORAGE_COMMIT_FAILED: + pAsciiErrorDescription = "committing the changes for document '#name#' failed"; + aAsciiParameterNames.push_back( "#name#" ); + break; + + case ERR_STORING_DATABASEDOC_FAILED: + pAsciiErrorDescription = "storing the database document failed"; + break; + + case ERR_COLLECTING_DOCUMENTS_FAILED: + pAsciiErrorDescription = "collecting the forms/reports of the database document failed"; + break; + + case ERR_UNEXPECTED_LIBSTORAGE_ELEMENT: + pAsciiErrorDescription = "unexpected #lib# storage element in document '#doc#', named '#element#'"; + aAsciiParameterNames.push_back( "#doc#" ); + aAsciiParameterNames.push_back( "#libstore#" ); + aAsciiParameterNames.push_back( "#element#" ); + break; + + case ERR_CREATING_DBDOC_SCRIPT_STORAGE_FAILED: + pAsciiErrorDescription = "creating the database document's storage for #scripttype# scripts failed"; + aAsciiParameterNames.push_back( "#scripttype#" ); + break; + + case ERR_COMMITTING_SCRIPT_STORAGES_FAILED: + pAsciiErrorDescription = "saving the #scripttype# scripts for document '#doc#' failed"; + aAsciiParameterNames.push_back( "#scripttype#" ); + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_GENERAL_SCRIPT_MIGRATION_FAILURE: + pAsciiErrorDescription = "general error during migrationg #scripttype# scripts of document '#doc#'"; + aAsciiParameterNames.push_back( "#scripttype#" ); + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_GENERAL_MACRO_MIGRATION_FAILURE: + pAsciiErrorDescription = "general error during macro migration of document '#doc#'"; + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_UNKNOWN_SCRIPT_TYPE: + pAsciiErrorDescription = "unknown script type: #type#"; + aAsciiParameterNames.push_back( "#type#" ); + break; + + case ERR_UNKNOWN_SCRIPT_LANGUAGE: + pAsciiErrorDescription = "unknown script language: #lang#"; + aAsciiParameterNames.push_back( "#lang#" ); + break; + + case ERR_UNKNOWN_SCRIPT_NAME_FORMAT: + pAsciiErrorDescription = "unknown script name format: #script#"; + aAsciiParameterNames.push_back( "#script#" ); + break; + + case ERR_SCRIPT_TRANSLATION_FAILURE: + pAsciiErrorDescription = "analyzing/translating the script URL failed; script type: #type#; script: #code#"; + aAsciiParameterNames.push_back( "#type#" ); + aAsciiParameterNames.push_back( "#code#" ); + break; + + case ERR_INVALID_SCRIPT_DESCRIPTOR_FORMAT: + pAsciiErrorDescription = "invalid script descriptor format"; + break; + + case ERR_ADJUSTING_DOCUMENT_EVENTS_FAILED: + pAsciiErrorDescription = "adjusting events for document #doc# failed"; + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_ADJUSTING_FORMCOMP_EVENTS_FAILED: + pAsciiErrorDescription = "adjusting form component events for '#doc#' failed"; + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_BIND_SCRIPT_STORAGE_FAILED: + pAsciiErrorDescription = "binding to the script storage failed for document '#doc#'"; + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_REMOVE_SCRIPTS_STORAGE_FAILED: + pAsciiErrorDescription = "removing a scripts storage failed for document '#doc#'"; + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_DOCUMENT_BACKUP_FAILED: + pAsciiErrorDescription = "backing up the document to #location# failed"; + aAsciiParameterNames.push_back( "#location#" ); + break; + + case ERR_UNKNOWN_SCRIPT_FOLDER: + pAsciiErrorDescription = "unknown script folder '#name#' in document '#doc#'"; + aAsciiParameterNames.push_back( "#doc#" ); + aAsciiParameterNames.push_back( "#name#" ); + break; + + case ERR_EXAMINING_SCRIPTS_FOLDER_FAILED: + pAsciiErrorDescription = "examining the 'Scripts' folder failed for document '#doc#'"; + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_PASSWORD_VERIFICATION_FAILED: + pAsciiErrorDescription = "password verification failed for document '#doc#', #libtype# library '#name#'"; + aAsciiParameterNames.push_back( "#doc#" ); + aAsciiParameterNames.push_back( "#libtype#" ); + aAsciiParameterNames.push_back( "#name#" ); + break; + + // do *not* add a default case here: Without a default, some compilers will warn you when + // you miss a newly-introduced enum value here + } + OSL_ENSURE( pAsciiErrorDescription, "lcl_appendErrorDescription: no error message!" ); + if ( pAsciiErrorDescription ) + { + ::rtl::OUString sSubstituted( ::rtl::OUString::createFromAscii( pAsciiErrorDescription ) ); + OSL_ENSURE( aAsciiParameterNames.size() == _rError.aErrorDetails.size(), + "lcl_appendErrorDescription: unexpected number of error message parameters!" ); + + for ( size_t i=0; i < ::std::min( aAsciiParameterNames.size(), _rError.aErrorDetails.size() ); ++i ) + { + ::comphelper::string::searchAndReplaceAsciiI( sSubstituted, aAsciiParameterNames[i], + _rError.aErrorDetails[i] ); + } + + _inout_rBuffer.append( sSubstituted ); + } + } + + //---------------------------------------------------------------- + void lcl_describeErrors( ::rtl::OUStringBuffer& _rBuffer, const ErrorLog& _rErrors, const USHORT _nHeadingResId ) { - USHORT nResId( 0 ); + _rBuffer.appendAscii( "=== " ); + _rBuffer.append ( String( MacroMigrationResId( _nHeadingResId ) ) ); + _rBuffer.appendAscii( " ===\n" ); - switch ( _eType ) + String sException( MacroMigrationResId( STR_EXCEPTION ) ); + + for ( ErrorLog::const_iterator error = _rErrors.begin(); + error != _rErrors.end(); + ++error + ) { - case eBasic: nResId = STR_OOO_BASIC; break; - case eBeanShell: nResId = STR_BEAN_SHELL; break; - case eJavaScript: nResId = STR_JAVA_SCRIPT; break; - case ePython: nResId = STR_PYTHON; break; - case eJava: nResId = STR_JAVA; break; - case eDialog: nResId = STR_DIALOG; break; + _rBuffer.append( sal_Unicode( '-' ) ); + _rBuffer.append( sal_Unicode( ' ' ) ); + lcl_appendErrorDescription( _rBuffer, *error ); + _rBuffer.append( sal_Unicode( '\n' ) ); + + if ( !error->aCaughtException.hasValue() ) + continue; + + _rBuffer.append( sException ); + _rBuffer.append( ::comphelper::anyToString( error->aCaughtException ) ); + _rBuffer.append( sal_Unicode( '\n' ) ); + _rBuffer.append( sal_Unicode( '\n' ) ); } - OSL_ENSURE( nResId != 0, "lcl_getScriptTypeDisplayName: illegal script type!" ); - return nResId ? String( MacroMigrationResId( nResId ) ) : String(); } } @@ -236,54 +422,65 @@ namespace dbmm { ::rtl::OUStringBuffer aBuffer; - String sBackedUp( MacroMigrationResId( STR_SAVED_COPY_TO ) ); - sBackedUp.SearchAndReplaceAllAscii( "$location$", m_pData->sBackupLocation ); - - aBuffer.appendAscii( "=== " ); - aBuffer.append ( String( MacroMigrationResId( STR_DATABASE_DOCUMENT ) ) ); - aBuffer.appendAscii( " ===\n" ); - aBuffer.append ( sBackedUp ); - aBuffer.appendAscii( "\n\n" ); - - String sMovedLibTemplate( MacroMigrationResId( STR_MOVED_LIBRARY ) ); - - for ( DocumentLogs::const_iterator doc = m_pData->aDocumentLogs.begin(); - doc != m_pData->aDocumentLogs.end(); - ++doc - ) + if ( m_pData->sBackupLocation.getLength() ) { - const DocumentEntry& rDoc( doc->second ); - - if ( rDoc.aMovedLibraries.empty() ) - continue; - - String sDocTitle( MacroMigrationResId( rDoc.eType == eForm ? STR_FORM : STR_REPORT ) ); - sDocTitle.SearchAndReplaceAllAscii( "$name$", rDoc.sName ); + String sBackedUp( MacroMigrationResId( STR_SAVED_COPY_TO ) ); + sBackedUp.SearchAndReplaceAllAscii( "$location$", m_pData->sBackupLocation ); aBuffer.appendAscii( "=== " ); - aBuffer.append ( sDocTitle ); + aBuffer.append ( String( MacroMigrationResId( STR_DATABASE_DOCUMENT ) ) ); aBuffer.appendAscii( " ===\n" ); + aBuffer.append ( sBackedUp ); + aBuffer.appendAscii( "\n\n" ); + } - for ( ::std::vector< LibraryEntry >::const_iterator lib = rDoc.aMovedLibraries.begin(); - lib != rDoc.aMovedLibraries.end(); - ++lib + if ( !m_pData->aFailures.empty() ) + { + lcl_describeErrors( aBuffer, m_pData->aFailures + , STR_ERRORS ); + } + else + { + String sMovedLibTemplate( MacroMigrationResId( STR_MOVED_LIBRARY ) ); + + for ( DocumentLogs::const_iterator doc = m_pData->aDocumentLogs.begin(); + doc != m_pData->aDocumentLogs.end(); + ++doc ) { - String sMovedLib( sMovedLibTemplate ); - sMovedLib.SearchAndReplaceAllAscii( "$type$", lcl_getScriptTypeDisplayName( lib->eType ) ); - sMovedLib.SearchAndReplaceAllAscii( "$old$", lib->sOldName ); - sMovedLib.SearchAndReplaceAllAscii( "$new$", lib->sNewName ); + const DocumentEntry& rDoc( doc->second ); - aBuffer.append ( sMovedLib ); - aBuffer.appendAscii( "\n" ); - } + if ( rDoc.aMovedLibraries.empty() ) + continue; - if ( !rDoc.bSuccess ) - { - // TODO + String sDocTitle( MacroMigrationResId( rDoc.eType == eForm ? STR_FORM : STR_REPORT ) ); + sDocTitle.SearchAndReplaceAllAscii( "$name$", rDoc.sName ); + + aBuffer.appendAscii( "=== " ); + aBuffer.append ( sDocTitle ); + aBuffer.appendAscii( " ===\n" ); + + for ( ::std::vector< LibraryEntry >::const_iterator lib = rDoc.aMovedLibraries.begin(); + lib != rDoc.aMovedLibraries.end(); + ++lib + ) + { + String sMovedLib( sMovedLibTemplate ); + sMovedLib.SearchAndReplaceAllAscii( "$type$", getScriptTypeDisplayName( lib->eType ) ); + sMovedLib.SearchAndReplaceAllAscii( "$old$", lib->sOldName ); + sMovedLib.SearchAndReplaceAllAscii( "$new$", lib->sNewName ); + + aBuffer.append( sMovedLib ); + aBuffer.append( sal_Unicode( '\n' ) ); + } + + aBuffer.append( sal_Unicode( '\n' ) ); } + } - aBuffer.appendAscii( "\n" ); + if ( !m_pData->aWarnings.empty() ) + { + lcl_describeErrors( aBuffer, m_pData->aWarnings, STR_WARNINGS ); } return aBuffer.makeStringAndClear(); diff --git a/dbaccess/source/ext/macromigration/migrationlog.hxx b/dbaccess/source/ext/macromigration/migrationlog.hxx index 67c9a7d60..4a23dd2b8 100644 --- a/dbaccess/source/ext/macromigration/migrationlog.hxx +++ b/dbaccess/source/ext/macromigration/migrationlog.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: migrationlog.hxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.2 $ * * This file is part of OpenOffice.org. * @@ -46,6 +46,7 @@ namespace dbmm //........................................................................ typedef sal_Int16 DocumentID; + struct MigrationError; //==================================================================== //= MigrationLog @@ -60,6 +61,17 @@ namespace dbmm //---------------------------------------------------------------- //- event logging + /** logs an unrecoverable error during the migration process + */ + void logFailure( const MigrationError& _rError ); + + /** logs a recoverable (or at least ignorable) error during the migration process + */ + void logRecoverable( const MigrationError& _rError ); + + /// checks whether logFailure has been called + bool hadFailure() const; + /// logs the fact that the database document has been backed up void backedUpDocument( const ::rtl::OUString& _rNewDocumentLocation ); @@ -80,7 +92,7 @@ namespace dbmm /** logs that the migration for a certain document has been finished */ - void finishedDocument( const DocumentID _nDocID, const bool _bSuccessful ); + void finishedDocument( const DocumentID _nDocID ); //---------------------------------------------------------------- //- information retrieval diff --git a/dbaccess/source/ext/macromigration/migrationprogress.hxx b/dbaccess/source/ext/macromigration/migrationprogress.hxx index 0db16fba9..84ff58722 100644 --- a/dbaccess/source/ext/macromigration/migrationprogress.hxx +++ b/dbaccess/source/ext/macromigration/migrationprogress.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: migrationprogress.hxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.1 $ * * This file is part of OpenOffice.org. * @@ -40,7 +40,7 @@ namespace dbmm //........................................................................ //==================================================================== - //= MigrationProgress + //= IMigrationProgress //==================================================================== class SAL_NO_VTABLE IMigrationProgress { diff --git a/dbaccess/source/ext/macromigration/progressmixer.cxx b/dbaccess/source/ext/macromigration/progressmixer.cxx new file mode 100644 index 000000000..0dfdee019 --- /dev/null +++ b/dbaccess/source/ext/macromigration/progressmixer.cxx @@ -0,0 +1,218 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2008 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* $RCSfile: progressmixer.cxx,v $ +* +* $Revision: 1.1.2.1 $ +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "progressmixer.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#include <osl/diagnose.h> + +#include <map> + +//........................................................................ +namespace dbmm +{ +//........................................................................ + + /** === begin UNO using === **/ + /** === end UNO using === **/ + +#define OVERALL_RANGE 100000 + + //==================================================================== + //= misc types + //==================================================================== + struct PhaseData + { + // the weight of the phase, relative to all other phases + PhaseWeight nWeight; + // the "local" range of the phase + sal_uInt32 nRange; + // this is the point in the "overall range" at which this phase starts + sal_uInt32 nGlobalStart; + /** the "global" range of the phase, i.e. its range after weighting with all other + phases + */ + sal_uInt32 nGlobalRange; + + PhaseData() + :nWeight(1) + ,nRange(100) + ,nGlobalStart(0) + ,nGlobalRange(100) + { + } + + PhaseData( const PhaseWeight _nWeight ) + :nWeight( _nWeight ) + ,nRange(100) + ,nGlobalStart(0) + ,nGlobalRange(100) + { + } + }; + + typedef ::std::map< PhaseID, PhaseData > Phases; + + //==================================================================== + //= ProgressMixer_Data + //==================================================================== + struct ProgressMixer_Data + { + Phases aPhases; + Phases::iterator pCurrentPhase; + sal_uInt32 nWeightSum; /// the cached sum of the weights + double nOverallStretch; + IProgressConsumer& rConsumer; + + ProgressMixer_Data( IProgressConsumer& _rConsumer ) + :aPhases() + ,pCurrentPhase( aPhases.end() ) + ,nWeightSum( 0 ) + ,nOverallStretch( 0 ) + ,rConsumer( _rConsumer ) + { + } + }; + + //-------------------------------------------------------------------- + namespace + { + //---------------------------------------------------------------- + bool lcl_isRunning( const ProgressMixer_Data& _rData ) + { + return _rData.pCurrentPhase != _rData.aPhases.end(); + } + + //---------------------------------------------------------------- + void lcl_ensureInitialized( ProgressMixer_Data& _rData ) + { + OSL_PRECOND( _rData.nWeightSum, "lcl_ensureInitialized: we have no phases, this will crash!" ); + + if ( _rData.nOverallStretch ) + return; + + _rData.nOverallStretch = 1.0 * OVERALL_RANGE / _rData.nWeightSum; + + // tell the single phases their "overall starting point" + PhaseWeight nRunningWeight( 0 ); + for ( Phases::iterator phase = _rData.aPhases.begin(); + phase != _rData.aPhases.end(); + ++phase + ) + { + phase->second.nGlobalStart = (sal_uInt32)( nRunningWeight * _rData.nOverallStretch ); + nRunningWeight += phase->second.nWeight; + + sal_uInt32 nNextPhaseStart = (sal_uInt32)( nRunningWeight * _rData.nOverallStretch ); + phase->second.nGlobalRange = nNextPhaseStart - phase->second.nGlobalStart; + } + + _rData.rConsumer.start( OVERALL_RANGE ); + } + } + + //==================================================================== + //= ProgressMixer + //==================================================================== + //-------------------------------------------------------------------- + ProgressMixer::ProgressMixer( IProgressConsumer& _rConsumer ) + :m_pData( new ProgressMixer_Data( _rConsumer ) ) + { + } + + //-------------------------------------------------------------------- + ProgressMixer::~ProgressMixer() + { + } + + //-------------------------------------------------------------------- + void ProgressMixer::registerPhase( const PhaseID _nID, const PhaseWeight _nWeight ) + { + OSL_PRECOND( !lcl_isRunning( *m_pData ), "ProgressMixer::registerPhase: already running!" ); + OSL_ENSURE( m_pData->aPhases.find( _nID ) == m_pData->aPhases.end(), + "ProgressMixer::registerPhase: ID already used!" ); + m_pData->aPhases[ _nID ] = PhaseData( _nWeight ); + m_pData->nWeightSum += _nWeight; + } + + //-------------------------------------------------------------------- + void ProgressMixer::startPhase( const PhaseID _nID, const sal_uInt32 _nPhaseRange ) + { + OSL_ENSURE( m_pData->aPhases.find( _nID ) != m_pData->aPhases.end(), + "ProgresMixer::startPhase: unknown phase!" ); + + m_pData->aPhases[ _nID ].nRange = _nPhaseRange; + m_pData->pCurrentPhase = m_pData->aPhases.find( _nID ); + } + + //-------------------------------------------------------------------- + void ProgressMixer::advancePhase( const sal_uInt32 _nPhaseProgress ) + { + OSL_PRECOND( lcl_isRunning( *m_pData ), "ProgresMixer::advancePhase: not running!" ); + + // in case this is the first call, ensure all the ranges/weights are calculated + // correctly + lcl_ensureInitialized( *m_pData ); + + const PhaseData& rPhase( m_pData->pCurrentPhase->second ); + + double nLocalProgress = 1.0 * _nPhaseProgress / rPhase.nRange; + sal_uInt32 nOverallProgress = (sal_uInt32) + ( rPhase.nGlobalStart + nLocalProgress * rPhase.nGlobalRange ); + + m_pData->rConsumer.advance( nOverallProgress ); + } + + //-------------------------------------------------------------------- + void ProgressMixer::endPhase() + { + OSL_PRECOND( lcl_isRunning( *m_pData ), "ProgresMixer::endPhase: not running!" ); + + // in case this is the first call, ensure all the ranges/weights are calculated + // correctly + lcl_ensureInitialized( *m_pData ); + + // simply assume the phase's complete range is over + advancePhase( m_pData->pCurrentPhase->second.nRange ); + + // if that's the last phase, this is the "global end", too + Phases::const_iterator pNextPhase( m_pData->pCurrentPhase ); + ++pNextPhase; + if ( pNextPhase == m_pData->aPhases.end() ) + m_pData->rConsumer.end(); + } + +//........................................................................ +} // namespace dbmm +//........................................................................ diff --git a/dbaccess/source/ext/macromigration/progressmixer.hxx b/dbaccess/source/ext/macromigration/progressmixer.hxx new file mode 100644 index 000000000..8290eca7e --- /dev/null +++ b/dbaccess/source/ext/macromigration/progressmixer.hxx @@ -0,0 +1,103 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2008 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* $RCSfile: progressmixer.hxx,v $ +* +* $Revision: 1.1.2.1 $ +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +************************************************************************/ + +#ifndef DBACCESS_PROGRESSMIXER_HXX +#define DBACCESS_PROGRESSMIXER_HXX + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#include <sal/types.h> + +#include <memory> + +//........................................................................ +namespace dbmm +{ +//........................................................................ + + typedef sal_uInt32 PhaseID; + typedef sal_uInt32 PhaseWeight; + + //==================================================================== + //= IProgressConsumer + //==================================================================== + class SAL_NO_VTABLE IProgressConsumer + { + public: + virtual void start( sal_uInt32 _nRange ) = 0; + virtual void advance( sal_uInt32 _nValue ) = 0; + virtual void end() = 0; + }; + + //==================================================================== + //= ProgressMixer + //==================================================================== + struct ProgressMixer_Data; + /** a class which mixes (i.e. concatenates) progress values from different + sources/phases, with different weight + */ + class ProgressMixer + { + public: + ProgressMixer( IProgressConsumer& _rConsumer ); + ~ProgressMixer(); + + /** registers a phase of the process, which has the given weight + in the overall process + @precond + the progress is not runnig, yet + */ + void registerPhase( const PhaseID _nID, const PhaseWeight _nWeight ); + + /** enters the phase with the given ID, with the phase having + the given overall range + */ + void startPhase( const PhaseID _nID, const sal_uInt32 _nPhaseRange ); + + /** announces a new progress in the current phase. + + The given phase progress must be between 0 and the overall phase range + as specified in ->startPhase. + */ + void advancePhase( const sal_uInt32 _nPhaseProgress ); + + /** leaves the current phase, which has been started with ->startPhase previously + */ + void endPhase(); + + private: + ::std::auto_ptr< ProgressMixer_Data > m_pData; + }; + +//........................................................................ +} // namespace dbmm +//........................................................................ + +#endif // DBACCESS_PROGRESSMIXER_HXX |