/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_dbaccess.hxx"

#include "dbmm_global.hrc"
#include "dbmm_module.hxx"
#include "dbmm_types.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>
#include <com/sun/star/sdb/XReportDocumentsSupplier.hpp>
#include <com/sun/star/util/XCloseable.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/frame/XComponentLoader.hpp>
#include <com/sun/star/ucb/XCommandProcessor.hpp>
#include <com/sun/star/ucb/XContent.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>
#include <com/sun/star/io/WrongFormatException.hpp>
#include <com/sun/star/script/XScriptEventsSupplier.hpp>
#include <com/sun/star/io/XInputStreamProvider.hpp>
/** === end UNO includes === **/

#include <comphelper/documentinfo.hxx>
#include <comphelper/interaction.hxx>
#include <comphelper/namedvaluecollection.hxx>
#include <comphelper/storagehelper.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 <xmlscript/xmldlg_imexp.hxx>

#include <vector>
#include <set>

#define DEFAULT_DOC_PROGRESS_RANGE  100000

//........................................................................
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::sdb::XFormDocumentsSupplier;
    using ::com::sun::star::sdb::XReportDocumentsSupplier;
    using ::com::sun::star::container::XNameAccess;
    using ::com::sun::star::uno::Sequence;
    using ::com::sun::star::util::XCloseable;
    using ::com::sun::star::util::CloseVetoException;
    using ::com::sun::star::lang::XComponent;
    using ::com::sun::star::frame::XModel;
    using ::com::sun::star::frame::XComponentLoader;
    using ::com::sun::star::ucb::XCommandProcessor;
    using ::com::sun::star::ucb::XContent;
    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;
    using ::com::sun::star::io::WrongFormatException;
    using ::com::sun::star::script::XScriptEventsSupplier;
    using ::com::sun::star::io::XInputStreamProvider;
    using ::com::sun::star::io::XInputStream;
    /** === 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;
        Reference< XModel >             xDocument;          // valid only temporarily
        ::rtl::OUString                 sHierarchicalName;
        SubDocumentType                 eType;
        size_t                          nNumber;

        SubDocument( const Reference< XCommandProcessor >& _rxCommandProcessor, const ::rtl::OUString& _rName,
                const SubDocumentType _eType, const size_t _nNumber )
            :xCommandProcessor( _rxCommandProcessor )
            ,xDocument()
            ,sHierarchicalName( _rName )
            ,eType( _eType )
            ,nNumber( _nNumber )
        {
        }
    };

    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 );
        }

        //----------------------------------------------------------------
        ::rtl::OUString lcl_getMimeType_nothrow( const Reference< XCommandProcessor >& _rxContent )
        {
            ::rtl::OUString sMimeType;
            try
            {
                Reference< XContent > xContent( _rxContent, UNO_QUERY_THROW );
                sMimeType = xContent->getContentType();
            }
            catch( const Exception& )
            {
            	DBG_UNHANDLED_EXCEPTION();
            }
            return sMimeType;
        }

        //----------------------------------------------------------------
        enum OpenDocResult
        {
            eOpenedDoc,
            eIgnoreDoc,
            eFailure
        };

        //----------------------------------------------------------------
        static OpenDocResult 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& )
            {
                Any aError( ::cppu::getCaughtException() );

                bool bCausedByNewStyleReport =
                        ( _rDocument.eType == eReport )
                    &&  ( aError.isExtractableTo( ::cppu::UnoType< WrongFormatException >::get() ) )
                    &&  ( lcl_getMimeType_nothrow( _rDocument.xCommandProcessor ).equalsAscii( "application/vnd.sun.xml.report" ) );

                if ( bCausedByNewStyleReport )
                {
                    _rLogger.logRecoverable( MigrationError(
                        ERR_NEW_STYLE_REPORT,
                        lcl_getSubDocumentDescription( _rDocument )
                    ) );
                    return eIgnoreDoc;
                }
                else
                {
                    _rLogger.logFailure( MigrationError(
                        ERR_OPENING_SUB_DOCUMENT_FAILED,
                        lcl_getSubDocumentDescription( _rDocument ),
                        aError
                    ) );
                }
            }
            return _rDocument.xDocument.is() ? eOpenedDoc : eFailure;
        }

	    //----------------------------------------------------------------
        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
    {
    public:
        MigrationEngine_Impl(
            const ::comphelper::ComponentContext& _rContext,
            const Reference< XOfficeDatabaseDocument >& _rxDocument,
            IMigrationProgress& _rProgress,
            MigrationLog& _rLogger
        );
        ~MigrationEngine_Impl();

        inline  size_t      getFormCount() const    { return m_nFormCount; }
        inline  size_t      getReportCount()const   { return m_nReportCount; }
        bool    migrateAll();

    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;

    private:
        /** collects a description of all sub documents of our database document

            @return
                <TRUE/> if and only if collecting the documents was successful
        */
        bool    impl_collectSubDocuments_nothrow();

        /** 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;

        /** adjusts the events for the given dialog/element, taking into account the new names
            of the moved libraries
        */
        void    impl_adjustDialogElementEvents_throw(
                    const Reference< XInterface >& _rxElement
                ) const;

        /** adjusts the events in the given dialog, and its controls, taking into account the new names
            of the moved libraries
        */
        bool    impl_adjustDialogEvents_nothrow(
                    Any& _inout_rDialogLibraryElement,
                    const ::rtl::OUString& _rDocName,
                    const ::rtl::OUString& _rDialogLibName,
                    const ::rtl::OUString& _rDialogName
                ) 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;
    };

	//====================================================================
	//= MigrationEngine_Impl - implementation
	//====================================================================
	//--------------------------------------------------------------------
    MigrationEngine_Impl::MigrationEngine_Impl( const ::comphelper::ComponentContext& _rContext,
            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 )
    {
        OSL_VERIFY( impl_collectSubDocuments_nothrow() );
    }

	//--------------------------------------------------------------------
    MigrationEngine_Impl::~MigrationEngine_Impl()
    {
    }

	//--------------------------------------------------------------------
    bool MigrationEngine_Impl::migrateAll()
    {
        if  ( m_aSubDocs.empty() )
        {
            OSL_ENSURE( false, "MigrationEngine_Impl::migrateAll: no forms/reports found!" );
            // The whole migration wizard is not expected to be called when there are no forms/reports
            // with macros, not to mention when there are no forms/reports at all.
            return false;
        }

        // initialize global progress
        sal_Int32 nOverallRange( m_aSubDocs.size() );
        String sProgressSkeleton = String( MacroMigrationResId( STR_OVERALL_PROGRESS ) );
        sProgressSkeleton.SearchAndReplaceAscii( "$overall$", String::CreateFromInt32( nOverallRange ) );

        m_rProgress.start( nOverallRange );

        for (   SubDocuments::const_iterator doc = m_aSubDocs.begin();
                doc != m_aSubDocs.end();
                ++doc
            )
        {
            sal_Int32 nOverallProgressValue( doc - m_aSubDocs.begin() + 1 );
            // update overall progress text
            ::rtl::OUString sOverallProgress( sProgressSkeleton );
            ::comphelper::string::searchAndReplaceAsciiI( sOverallProgress, "$current$", ::rtl::OUString::valueOf( nOverallProgressValue ) );
            m_rProgress.setOverallProgressText( sOverallProgress );

            // migrate document
            if ( !impl_handleDocument_nothrow( *doc ) )
                return false;

            // update overall progress vallue
            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;
    }

	//--------------------------------------------------------------------
    namespace
    {
        void lcl_collectHierarchicalElementNames_throw(
            const Reference< XNameAccess >& _rxContainer, const ::rtl::OUString& _rContainerLoc,
            SubDocuments& _out_rDocs, const SubDocumentType _eType, size_t& _io_counter )
        {
            const ::rtl::OUString sHierarhicalBase(
                _rContainerLoc.getLength()  ?   ::rtl::OUStringBuffer( _rContainerLoc ).appendAscii( "/" ).makeStringAndClear()
                                            :   ::rtl::OUString() );

            Sequence< ::rtl::OUString > aElementNames( _rxContainer->getElementNames() );
            for (   const ::rtl::OUString* elementName = aElementNames.getConstArray();
                    elementName != aElementNames.getConstArray() + aElementNames.getLength();
                    ++elementName
                )
            {
                Any aElement( _rxContainer->getByName( *elementName ) );
                ::rtl::OUString sElementName( ::rtl::OUStringBuffer( sHierarhicalBase ).append( *elementName ) );

                Reference< XNameAccess > xSubContainer( aElement, UNO_QUERY );
                if ( xSubContainer.is() )
                {
                    lcl_collectHierarchicalElementNames_throw( xSubContainer, sElementName, _out_rDocs, _eType, _io_counter );
                }
                else
                {
                    Reference< XCommandProcessor > xCommandProcessor( aElement, UNO_QUERY );
                    OSL_ENSURE( xCommandProcessor.is(), "lcl_collectHierarchicalElementNames_throw: no container, and no comand processor? What *is* it, then?!" );
                    if ( xCommandProcessor.is() )
                    {
                        _out_rDocs.push_back( SubDocument( xCommandProcessor, sElementName, _eType, ++_io_counter ) );
                    }
                }
            }
        }
    }

    //--------------------------------------------------------------------
    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
        {
            Reference< XNameAccess > xDocContainer( m_xDocument->getFormDocuments(), UNO_SET_THROW );
            m_nFormCount = 0;
            lcl_collectHierarchicalElementNames_throw( xDocContainer, ::rtl::OUString(), m_aSubDocs, eForm, m_nFormCount );

            xDocContainer.set( m_xDocument->getReportDocuments(), UNO_SET_THROW );
            m_nReportCount = 0;
            lcl_collectHierarchicalElementNames_throw( xDocContainer, ::rtl::OUString(), m_aSubDocs, eReport, m_nReportCount );
        }
        catch( const 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 );
        OpenDocResult eResult = lcl_loadSubDocument_nothrow( aSubDocument, pStatusIndicator.get(), m_rLogger );
        if ( eResult != eOpenedDoc )
        {
            pStatusIndicator->dispose();
            m_rProgress.endObject();
            m_rLogger.finishedDocument( m_nCurrentDocumentID );
			m_nCurrentDocumentID = -1;
            return ( eResult == eIgnoreDoc );
        }

        // -----------------
        // 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 );
                // order matters: First Basic scripts, then dialogs. So we can adjust references from the latter
                // to the former

        // 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
        if ( m_rLogger.movedAnyLibrary( m_nCurrentDocumentID ) )
        {
            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 ::rtl::OUString lcl_createTargetLibName( const SubDocument& _rDocument,
            const ::rtl::OUString& _rSourceLibName, const Reference< XNameAccess >& _rxTargetContainer )
        {
            // The new library name is composed from the prefix, the base name, and the old library name.
            const ::rtl::OUString sPrefix( ::rtl::OUString::createFromAscii( _rDocument.eType == eForm ? "Form_" : "Report_" ) );

            ::rtl::OUString sBaseName( _rDocument.sHierarchicalName.copy(
                _rDocument.sHierarchicalName.lastIndexOf( '/' ) + 1 ) );
            // Normalize this name. In our current storage implementation (and script containers in a document
            // are finally mapped to sub storages of the document storage), not all characters are allowed.
            // The bug requesting to change this is #i95409#.
            // Unfortunately, the storage implementation does not complain if you use invalid characters/names, but instead
            // it silently accepts them, and produces garbage in the file (#i95408).
            // So, until especially the former is fixed, we need to strip the name from all invalid characters.
            // #i95865# / 2008-11-06 / frank.schoenheit@sun.com

            // The general idea is to replace invalid characters with '_'. However, since "valid" essentially means
            // ASCII only, this implies that for a lot of languages, we would simply replace everything with '_',
            // which of course is not desired.
            // So, we use a heuristics: If the name contains at most 3 invalid characters, and as many valid as invalid
            // characters, then we use the replacement. Otherwise, we just use a unambiguous number for the sub document.
            sal_Int32 nValid=0, nInvalid=0;
            const sal_Unicode* pBaseName = sBaseName.getStr();
            const sal_Int32 nBaseNameLen = sBaseName.getLength();
            for ( sal_Int32 i=0; i<nBaseNameLen; ++i )
            {
                if ( ::comphelper::OStorageHelper::IsValidZipEntryFileName( pBaseName + i, 1, sal_False ) )
                    ++nValid;
                else
                    ++nInvalid;
            }
            if ( ( nInvalid <= 3 ) && ( nInvalid * 2 <= nValid ) )
            {   // not "too many" invalid => replace them
                ::rtl::OUStringBuffer aReplacement;
                aReplacement.ensureCapacity( nBaseNameLen );
                aReplacement.append( sBaseName );
                const sal_Unicode* pReplacement = aReplacement.getStr();
                for ( sal_Int32 i=0; i<nBaseNameLen; ++i )
                {
                    if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( pReplacement + i, 1, sal_False ) )
                        aReplacement.setCharAt( i, '_' );
                }
                sBaseName = aReplacement.makeStringAndClear();

                ::rtl::OUStringBuffer aNewLibNameAttempt;
                aNewLibNameAttempt.append( sPrefix );
                aNewLibNameAttempt.append( sBaseName );
                aNewLibNameAttempt.appendAscii( "_" );
                aNewLibNameAttempt.append( _rSourceLibName );
                ::rtl::OUString sTargetName( aNewLibNameAttempt.makeStringAndClear() );
                if ( !_rxTargetContainer->hasByName( sTargetName ) )
                    return sTargetName;
            }

            // "too many" invalid characters, or the name composed with the base name was already used.
            // (The latter is valid, since there can be multiple sub documents with the same base name,
            // in different levels in the hierarchy.)
            // In this case, just use the umambiguous sub document number.
            ::rtl::OUStringBuffer aNewLibName;
            aNewLibName.append( sPrefix );
            aNewLibName.append( ::rtl::OUString::valueOf( sal_Int64( _rDocument.nNumber ) ) );
            aNewLibName.appendAscii( "_" );
            aNewLibName.append( _rSourceLibName );
            return aNewLibName.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() )
            {
                m_rLogger.logFailure( MigrationError(
                    ERR_UNKNOWN_SCRIPT_FOLDER,
                    lcl_getSubDocumentDescription( _rDocument ),
                    *aElementNames.begin()
                ) );
                return false;
            }
        }
        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 )
                )
            {
                // no scripts at all, or no scripts of the given type
                _rProgress.startPhase( _nPhaseID, 1 );
                _rProgress.endPhase();
                return !m_rLogger.hadFailure();
            }

            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
                )
            {
                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,
                    getScriptTypeDisplayName( _eScriptType ),
                    lcl_getSubDocumentDescription( _rDocument )
                ) );
                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;
        }

        // log the error, if any
        if ( !bSuccess )
        {
            m_rLogger.logFailure( MigrationError(
                ERR_GENERAL_SCRIPT_MIGRATION_FAILURE,
                getScriptTypeDisplayName( _eScriptType ),
                lcl_getSubDocumentDescription( _rDocument ),
                aException
            ) );
        }

        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() )
            {
                bSuccess = true;
                break;
            }

            // 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!" );

                        // if this is a dialog, adjust the references to scripts
                        if ( _eScriptType == eDialog )
                        {
                            impl_adjustDialogEvents_nothrow( aElement, lcl_getSubDocumentDescription( _rDocument ),
                                *pSourceLibName, *pSourceElementName );
                        }

                        xTargetLib->insertByName( *pSourceElementName, aElement );
                    }

                    // transfer the read-only flag
                    xTargetLibraries->setLibraryReadOnly(
                        sNewLibName, xSourceLibraries->isLibraryReadOnly( *pSourceLibName ) );
                }

                // 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 );
            }

            // 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()
                )
            {
                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;
            }

            // 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_adjustScriptLibrary_nothrow( ScriptEventDescriptor& _inout_rScriptEvent ) const
    {
        if ( _inout_rScriptEvent.ScriptType.getLength() && _inout_rScriptEvent.ScriptCode.getLength() )
            return impl_adjustScriptLibrary_nothrow( _inout_rScriptEvent.ScriptType, _inout_rScriptEvent.ScriptCode );
        return false;
    }

	//--------------------------------------------------------------------
    bool MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow( Any& _inout_rScriptDescriptor ) const
    {
        ::comphelper::NamedValueCollection aScriptDesc( _inout_rScriptDescriptor );

        ::rtl::OUString sScriptType;
        ::rtl::OUString sScript;
        try
        {
            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;
    }

	//--------------------------------------------------------------------
    void MigrationEngine_Impl::impl_adjustDialogElementEvents_throw( const Reference< XInterface >& _rxElement ) const
    {
        Reference< XScriptEventsSupplier > xEventsSupplier( _rxElement, UNO_QUERY_THROW );
        Reference< XNameReplace > xEvents( xEventsSupplier->getEvents(), UNO_QUERY_THROW );
        Sequence< ::rtl::OUString > aEventNames( xEvents->getElementNames() );

        const ::rtl::OUString* eventName = aEventNames.getArray();
        const ::rtl::OUString* eventNamesEnd = eventName + aEventNames.getLength();

        ScriptEventDescriptor aScriptEvent;
        for ( ; eventName != eventNamesEnd; ++eventName )
        {
            OSL_VERIFY( xEvents->getByName( *eventName ) >>= aScriptEvent );

            if ( !impl_adjustScriptLibrary_nothrow( aScriptEvent ) )
                continue;

            xEvents->replaceByName( *eventName, makeAny( aScriptEvent ) );
        }
    }

	//--------------------------------------------------------------------
    bool MigrationEngine_Impl::impl_adjustDialogEvents_nothrow( Any& _inout_rDialogLibraryElement,
        const ::rtl::OUString& _rDocName, const ::rtl::OUString& _rDialogLibName, const ::rtl::OUString& _rDialogName ) const
    {
        try
        {
            // load a dialog model from the stream describing it
            Reference< XInputStreamProvider > xISP( _inout_rDialogLibraryElement, UNO_QUERY_THROW );
            Reference< XInputStream > xInput( xISP->createInputStream(), UNO_QUERY_THROW );

            Reference< XNameContainer > xDialogModel( m_aContext.createComponent( "com.sun.star.awt.UnoControlDialogModel" ), UNO_QUERY_THROW );
            ::xmlscript::importDialogModel( xInput, xDialogModel, m_aContext.getUNOContext() );

            // adjust the events of the dialog
            impl_adjustDialogElementEvents_throw( xDialogModel );

            // adjust the events of the controls
            Sequence< ::rtl::OUString > aControlNames( xDialogModel->getElementNames() );
            const ::rtl::OUString* controlName = aControlNames.getConstArray();
            const ::rtl::OUString* controlNamesEnd = controlName + aControlNames.getLength();
            for ( ; controlName != controlNamesEnd; ++controlName )
            {
                impl_adjustDialogElementEvents_throw( Reference< XInterface >( xDialogModel->getByName( *controlName ), UNO_QUERY ) );
            }

            // export dialog model
            xISP = ::xmlscript::exportDialogModel( xDialogModel, m_aContext.getUNOContext() );
            _inout_rDialogLibraryElement <<= xISP;
        }
        catch( const Exception& )
        {
            m_rLogger.logRecoverable( MigrationError(
                ERR_ADJUSTING_DIALOG_EVENTS_FAILED,
                _rDocName,
                _rDialogLibName,
                _rDialogName,
                ::cppu::getCaughtException()
            ) );
            return false;
        }
        return true;
    }

	//--------------------------------------------------------------------
    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() );

            bool bChangedComponentEvents = false;
            for (   ScriptEventDescriptor* scriptEvent = aEvents.getArray();
                    scriptEvent != aEvents.getArray() + aEvents.getLength();
                    ++scriptEvent
                )
            {
                if ( !impl_adjustScriptLibrary_nothrow( *scriptEvent ) )
                    continue;

                bChangedComponentEvents = true;
            }

            if ( bChangedComponentEvents )
                aComponent.setEvents( aEvents );

            // 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;
    }

	//--------------------------------------------------------------------
    bool MigrationEngine_Impl::impl_unprotectPasswordLibrary_throw( const Reference< XLibraryContainerPassword >& _rxPasswordManager,
            const ScriptType _eScriptType, const ::rtl::OUString& _rLibraryName ) const
    {
        // 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;
        }

    }

	//====================================================================
	//= MigrationEngine
	//====================================================================
	//--------------------------------------------------------------------
    MigrationEngine::MigrationEngine( const ::comphelper::ComponentContext& _rContext,
            const Reference< XOfficeDatabaseDocument >& _rxDocument, IMigrationProgress& _rProgress,
            MigrationLog& _rLogger )
        :m_pImpl( new MigrationEngine_Impl( _rContext, _rxDocument, _rProgress, _rLogger ) )
    {
    }

	//--------------------------------------------------------------------
    MigrationEngine::~MigrationEngine()
    {
    }

	//--------------------------------------------------------------------
    sal_Int32 MigrationEngine::getFormCount() const
    {
        return m_pImpl->getFormCount();
    }

	//--------------------------------------------------------------------
    sal_Int32 MigrationEngine::getReportCount() const
    {
        return m_pImpl->getReportCount();
    }

	//--------------------------------------------------------------------
    bool MigrationEngine::migrateAll()
    {
        return m_pImpl->migrateAll();
    }

//........................................................................
} // namespace dbmm
//........................................................................
