1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dbaccess.hxx"
30 
31 #include "dbmm_global.hrc"
32 #include "dbmm_module.hxx"
33 #include "dbmm_types.hxx"
34 #include "docinteraction.hxx"
35 #include "migrationengine.hxx"
36 #include "migrationerror.hxx"
37 #include "migrationprogress.hxx"
38 #include "migrationlog.hxx"
39 #include "progresscapture.hxx"
40 #include "progressmixer.hxx"
41 
42 /** === begin UNO includes === **/
43 #include <com/sun/star/sdb/XFormDocumentsSupplier.hpp>
44 #include <com/sun/star/sdb/XReportDocumentsSupplier.hpp>
45 #include <com/sun/star/util/XCloseable.hpp>
46 #include <com/sun/star/frame/XModel.hpp>
47 #include <com/sun/star/frame/XComponentLoader.hpp>
48 #include <com/sun/star/ucb/XCommandProcessor.hpp>
49 #include <com/sun/star/ucb/XContent.hpp>
50 #include <com/sun/star/embed/XComponentSupplier.hpp>
51 #include <com/sun/star/embed/ElementModes.hpp>
52 #include <com/sun/star/document/XStorageBasedDocument.hpp>
53 #include <com/sun/star/embed/XTransactedObject.hpp>
54 #include <com/sun/star/frame/XStorable.hpp>
55 #include <com/sun/star/embed/XEmbedPersist.hpp>
56 #include <com/sun/star/script/DocumentScriptLibraryContainer.hpp>
57 #include <com/sun/star/script/DocumentDialogLibraryContainer.hpp>
58 #include <com/sun/star/document/XEmbeddedScripts.hpp>
59 #include <com/sun/star/document/XEventsSupplier.hpp>
60 #include <com/sun/star/uri/UriReferenceFactory.hpp>
61 #include <com/sun/star/uri/XVndSunStarScriptUrlReference.hpp>
62 #include <com/sun/star/form/XFormsSupplier.hpp>
63 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
64 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
65 #include <com/sun/star/script/XEventAttacherManager.hpp>
66 #include <com/sun/star/script/XLibraryContainerPassword.hpp>
67 #include <com/sun/star/io/WrongFormatException.hpp>
68 #include <com/sun/star/script/XScriptEventsSupplier.hpp>
69 #include <com/sun/star/io/XInputStreamProvider.hpp>
70 /** === end UNO includes === **/
71 
72 #include <comphelper/documentinfo.hxx>
73 #include <comphelper/interaction.hxx>
74 #include <comphelper/namedvaluecollection.hxx>
75 #include <comphelper/storagehelper.hxx>
76 #include <comphelper/string.hxx>
77 #include <comphelper/types.hxx>
78 #include <cppuhelper/exc_hlp.hxx>
79 #include <tools/string.hxx>
80 #include <tools/diagnose_ex.h>
81 #include <rtl/ustrbuf.hxx>
82 #include <rtl/ref.hxx>
83 #include <unotools/sharedunocomponent.hxx>
84 #include <xmlscript/xmldlg_imexp.hxx>
85 
86 #include <vector>
87 #include <set>
88 
89 #define DEFAULT_DOC_PROGRESS_RANGE  100000
90 
91 //........................................................................
92 namespace dbmm
93 {
94 //........................................................................
95 
96 	/** === begin UNO using === **/
97 	using ::com::sun::star::uno::Reference;
98 	using ::com::sun::star::uno::XInterface;
99 	using ::com::sun::star::uno::UNO_QUERY;
100 	using ::com::sun::star::uno::UNO_QUERY_THROW;
101 	using ::com::sun::star::uno::UNO_SET_THROW;
102 	using ::com::sun::star::uno::Exception;
103 	using ::com::sun::star::uno::RuntimeException;
104 	using ::com::sun::star::uno::Any;
105 	using ::com::sun::star::uno::makeAny;
106     using ::com::sun::star::sdb::XOfficeDatabaseDocument;
107     using ::com::sun::star::sdb::XFormDocumentsSupplier;
108     using ::com::sun::star::sdb::XReportDocumentsSupplier;
109     using ::com::sun::star::container::XNameAccess;
110     using ::com::sun::star::uno::Sequence;
111     using ::com::sun::star::util::XCloseable;
112     using ::com::sun::star::util::CloseVetoException;
113     using ::com::sun::star::lang::XComponent;
114     using ::com::sun::star::frame::XModel;
115     using ::com::sun::star::frame::XComponentLoader;
116     using ::com::sun::star::ucb::XCommandProcessor;
117     using ::com::sun::star::ucb::XContent;
118     using ::com::sun::star::ucb::Command;
119     using ::com::sun::star::embed::XComponentSupplier;
120     using ::com::sun::star::task::XStatusIndicator;
121     using ::com::sun::star::embed::XStorage;
122     using ::com::sun::star::document::XStorageBasedDocument;
123     using ::com::sun::star::embed::XTransactedObject;
124     using ::com::sun::star::frame::XStorable;
125     using ::com::sun::star::embed::XEmbedPersist;
126     using ::com::sun::star::script::DocumentDialogLibraryContainer;
127     using ::com::sun::star::script::DocumentScriptLibraryContainer;
128     using ::com::sun::star::script::XStorageBasedLibraryContainer;
129     using ::com::sun::star::document::XEmbeddedScripts;
130     using ::com::sun::star::container::XNameContainer;
131     using ::com::sun::star::document::XEventsSupplier;
132     using ::com::sun::star::container::XNameReplace;
133     using com::sun::star::uri::UriReferenceFactory;
134     using com::sun::star::uri::XUriReferenceFactory;
135     using com::sun::star::uri::XVndSunStarScriptUrlReference;
136     using ::com::sun::star::form::XFormsSupplier;
137     using ::com::sun::star::drawing::XDrawPageSupplier;
138     using ::com::sun::star::drawing::XDrawPagesSupplier;
139     using ::com::sun::star::drawing::XDrawPage;
140     using ::com::sun::star::drawing::XDrawPages;
141     using ::com::sun::star::container::XIndexAccess;
142     using ::com::sun::star::script::XEventAttacherManager;
143     using ::com::sun::star::script::ScriptEventDescriptor;
144     using ::com::sun::star::script::XLibraryContainerPassword;
145     using ::com::sun::star::io::WrongFormatException;
146     using ::com::sun::star::script::XScriptEventsSupplier;
147     using ::com::sun::star::io::XInputStreamProvider;
148     using ::com::sun::star::io::XInputStream;
149     /** === end UNO using === **/
150     namespace ElementModes = ::com::sun::star::embed::ElementModes;
151 
152 // migration phases whose progresses are to be mixed into one progress
153 #define PHASE_JAVASCRIPT    1
154 #define PHASE_BEANSHELL     2
155 #define PHASE_PYTHON        3
156 #define PHASE_JAVA          4
157 #define PHASE_BASIC         5
158 #define PHASE_DIALOGS       6
159 
160     //====================================================================
161     //= SubDocument
162     //====================================================================
163     struct SubDocument
164     {
165         Reference< XCommandProcessor >  xCommandProcessor;
166         Reference< XModel >             xDocument;          // valid only temporarily
167         ::rtl::OUString                 sHierarchicalName;
168         SubDocumentType                 eType;
169         size_t                          nNumber;
170 
171         SubDocument( const Reference< XCommandProcessor >& _rxCommandProcessor, const ::rtl::OUString& _rName,
172                 const SubDocumentType _eType, const size_t _nNumber )
173             :xCommandProcessor( _rxCommandProcessor )
174             ,xDocument()
175             ,sHierarchicalName( _rName )
176             ,eType( _eType )
177             ,nNumber( _nNumber )
178         {
179         }
180     };
181 
182     typedef ::std::vector< SubDocument >    SubDocuments;
183 
184     //====================================================================
185 	//= helper
186 	//====================================================================
187     //--------------------------------------------------------------------
188     typedef ::utl::SharedUNOComponent< XStorage >   SharedStorage;
189 
190     namespace
191     {
192 	    //----------------------------------------------------------------
193         static const ::rtl::OUString& lcl_getScriptsStorageName()
194         {
195             static const ::rtl::OUString s_sScriptsStorageName( RTL_CONSTASCII_USTRINGPARAM( "Scripts" ) );
196             return s_sScriptsStorageName;
197         }
198 
199 	    //----------------------------------------------------------------
200         static const ::rtl::OUString& lcl_getScriptsSubStorageName( const ScriptType _eType )
201         {
202             static const ::rtl::OUString s_sBeanShell ( RTL_CONSTASCII_USTRINGPARAM( "beanshell" ) );
203             static const ::rtl::OUString s_sJavaScript( RTL_CONSTASCII_USTRINGPARAM( "javascript" ) );
204             static const ::rtl::OUString s_sPython    ( RTL_CONSTASCII_USTRINGPARAM( "python" ) );      // TODO: is this correct?
205             static const ::rtl::OUString s_sJava      ( RTL_CONSTASCII_USTRINGPARAM( "java" ) );
206 
207             switch ( _eType )
208             {
209             case eBeanShell:    return s_sBeanShell;
210             case eJavaScript:   return s_sJavaScript;
211             case ePython:       return s_sPython;
212             case eJava:         return s_sJava;
213             default:
214                 break;
215             }
216 
217             OSL_ENSURE( false, "lcl_getScriptsSubStorageName: illegal type!" );
218             static ::rtl::OUString s_sEmpty;
219             return s_sEmpty;
220         }
221 
222 	    //----------------------------------------------------------------
223         static bool lcl_getScriptTypeFromLanguage( const ::rtl::OUString& _rLanguage, ScriptType& _out_rScriptType )
224         {
225             struct LanguageMapping
226             {
227                 const sal_Char*     pAsciiLanguage;
228                 const ScriptType    eScriptType;
229 
230                 LanguageMapping( const sal_Char* _pAsciiLanguage, const ScriptType _eScriptType )
231                     :pAsciiLanguage( _pAsciiLanguage )
232                     ,eScriptType( _eScriptType )
233                 {
234                 }
235             }
236             aLanguageMapping[] =
237             {
238                 LanguageMapping( "JavaScript", eJavaScript ),
239                 LanguageMapping( "BeanShell",  eBeanShell ),
240                 LanguageMapping( "Java",       eJava ),
241                 LanguageMapping( "Python",     ePython ),          // TODO: is this correct?
242                 LanguageMapping( "Basic",      eBasic )
243             };
244             for ( size_t i=0; i < sizeof( aLanguageMapping ) / sizeof( aLanguageMapping[0] ); ++i )
245             {
246                 if ( _rLanguage.equalsAscii( aLanguageMapping[i].pAsciiLanguage ) )
247                 {
248                     _out_rScriptType = aLanguageMapping[i].eScriptType;
249                     return true;
250                 }
251             }
252             OSL_ENSURE( false, "lcl_getScriptTypeFromLanguage: unknown language!" );
253             return false;
254         }
255 
256         //----------------------------------------------------------------
257         ::rtl::OUString lcl_getSubDocumentDescription( const SubDocument& _rDocument )
258         {
259             ::rtl::OUString sObjectName = String( MacroMigrationResId( _rDocument.eType == eForm ? STR_FORM : STR_REPORT ) );
260             ::comphelper::string::searchAndReplaceAsciiI( sObjectName, "$name$", _rDocument.sHierarchicalName );
261             return sObjectName;
262         }
263 
264         //----------------------------------------------------------------
265         static Any lcl_executeCommand_throw( const Reference< XCommandProcessor >& _rxCommandProc,
266             const sal_Char* _pAsciiCommand )
267         {
268             OSL_PRECOND( _rxCommandProc.is(), "lcl_executeCommand_throw: illegal object!" );
269             if ( !_rxCommandProc.is() )
270                 return Any();
271 
272             Command aCommand;
273             aCommand.Name = ::rtl::OUString::createFromAscii( _pAsciiCommand );
274             return _rxCommandProc->execute(
275                 aCommand, _rxCommandProc->createCommandIdentifier(), NULL );
276         }
277 
278         //----------------------------------------------------------------
279         ::rtl::OUString lcl_getMimeType_nothrow( const Reference< XCommandProcessor >& _rxContent )
280         {
281             ::rtl::OUString sMimeType;
282             try
283             {
284                 Reference< XContent > xContent( _rxContent, UNO_QUERY_THROW );
285                 sMimeType = xContent->getContentType();
286             }
287             catch( const Exception& )
288             {
289             	DBG_UNHANDLED_EXCEPTION();
290             }
291             return sMimeType;
292         }
293 
294         //----------------------------------------------------------------
295         enum OpenDocResult
296         {
297             eOpenedDoc,
298             eIgnoreDoc,
299             eFailure
300         };
301 
302         //----------------------------------------------------------------
303         static OpenDocResult lcl_loadSubDocument_nothrow( SubDocument& _rDocument,
304             const Reference< XStatusIndicator >& _rxProgress, MigrationLog& _rLogger )
305         {
306             OSL_PRECOND( !_rDocument.xDocument.is(), "lcl_loadSubDocument_nothrow: already loaded!" );
307 
308             try
309             {
310                 ::comphelper::NamedValueCollection aLoadArgs;
311                 aLoadArgs.put( "Hidden", (sal_Bool)sal_True );
312                 aLoadArgs.put( "StatusIndicator", _rxProgress );
313 
314                 Reference< XCommandProcessor > xCommandProcessor( _rDocument.xCommandProcessor, UNO_SET_THROW );
315                 Command aCommand;
316                 aCommand.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "openDesign" ) );
317                 aCommand.Argument <<= aLoadArgs.getPropertyValues();
318                 Reference< XComponent > xDocComponent(
319                     xCommandProcessor->execute(
320                         aCommand, xCommandProcessor->createCommandIdentifier(), NULL
321                     ),
322                     UNO_QUERY
323                 );
324                 OSL_ENSURE( xDocComponent.is(), "lcl_loadSubDocument_nothrow: no component loaded!" );
325 
326                 _rDocument.xDocument.set( xDocComponent, UNO_QUERY_THROW );
327             }
328             catch( const Exception& )
329             {
330                 Any aError( ::cppu::getCaughtException() );
331 
332                 bool bCausedByNewStyleReport =
333                         ( _rDocument.eType == eReport )
334                     &&  ( aError.isExtractableTo( ::cppu::UnoType< WrongFormatException >::get() ) )
335                     &&  ( lcl_getMimeType_nothrow( _rDocument.xCommandProcessor ).equalsAscii( "application/vnd.sun.xml.report" ) );
336 
337                 if ( bCausedByNewStyleReport )
338                 {
339                     _rLogger.logRecoverable( MigrationError(
340                         ERR_NEW_STYLE_REPORT,
341                         lcl_getSubDocumentDescription( _rDocument )
342                     ) );
343                     return eIgnoreDoc;
344                 }
345                 else
346                 {
347                     _rLogger.logFailure( MigrationError(
348                         ERR_OPENING_SUB_DOCUMENT_FAILED,
349                         lcl_getSubDocumentDescription( _rDocument ),
350                         aError
351                     ) );
352                 }
353             }
354             return _rDocument.xDocument.is() ? eOpenedDoc : eFailure;
355         }
356 
357 	    //----------------------------------------------------------------
358         static bool lcl_unloadSubDocument_nothrow( SubDocument& _rDocument, MigrationLog& _rLogger )
359         {
360             bool bSuccess = false;
361             Any aException;
362             try
363             {
364                 OSL_VERIFY( lcl_executeCommand_throw( _rDocument.xCommandProcessor, "close" ) >>= bSuccess );
365             }
366             catch( const Exception& )
367             {
368                 aException = ::cppu::getCaughtException();
369             }
370 
371             // log the failure, if any
372             if ( !bSuccess )
373             {
374                 _rLogger.logFailure( MigrationError(
375                     ERR_CLOSING_SUB_DOCUMENT_FAILED,
376                     lcl_getSubDocumentDescription( _rDocument ),
377                     aException
378                 ) );
379             }
380 
381             _rDocument.xDocument.clear();
382             return bSuccess;
383         }
384 
385         //----------------------------------------------------------------
386         bool lcl_commitStorage_nothrow( const Reference< XStorage >& _rxStorage )
387         {
388             try
389             {
390                 Reference< XTransactedObject > xTrans( _rxStorage, UNO_QUERY_THROW );
391                 xTrans->commit();
392             }
393             catch( const Exception& )
394             {
395             	return false;
396             }
397             return true;
398         }
399 
400         //----------------------------------------------------------------
401         bool lcl_commitDocumentStorage_nothrow( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger )
402         {
403             bool bSuccess = false;
404             Any aException;
405             try
406             {
407                 Reference< XStorageBasedDocument > xStorageDoc( _rxDocument, UNO_QUERY_THROW );
408                 Reference< XStorage > xDocStorage( xStorageDoc->getDocumentStorage(), UNO_QUERY_THROW );
409                 bSuccess = lcl_commitStorage_nothrow( xDocStorage );
410             }
411             catch( const Exception& )
412             {
413                 aException = ::cppu::getCaughtException();
414             }
415 
416             // log the failure, if any
417             if ( !bSuccess )
418             {
419                 _rLogger.logFailure( MigrationError(
420                     ERR_STORAGE_COMMIT_FAILED,
421                     ::comphelper::DocumentInfo::getDocumentTitle( _rxDocument ),
422                     aException
423                 ) );
424             }
425         	return bSuccess;
426         }
427 
428         //----------------------------------------------------------------
429         bool lcl_storeDocument_nothrow( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger )
430         {
431             bool bSuccess = false;
432             Any aException;
433             try
434             {
435                 Reference< XStorable > xStorable( _rxDocument, UNO_QUERY_THROW );
436                 xStorable->store();
437                 bSuccess = true;
438             }
439             catch( const Exception& )
440             {
441                 aException = ::cppu::getCaughtException();
442             }
443 
444             // log the failure, if any
445             if ( !bSuccess )
446             {
447                 _rLogger.logFailure( MigrationError(
448                     ERR_STORING_DATABASEDOC_FAILED,
449                     aException
450                 ) );
451             }
452         	return bSuccess;
453         }
454 
455         //----------------------------------------------------------------
456         bool lcl_storeEmbeddedDocument_nothrow( const SubDocument& _rDocument )
457         {
458             try
459             {
460                 lcl_executeCommand_throw( _rDocument.xCommandProcessor, "store" );
461             }
462             catch( const Exception& )
463             {
464             	DBG_UNHANDLED_EXCEPTION();
465                 return false;
466             }
467             return true;
468         }
469     }
470 
471     //====================================================================
472 	//= DrawPageIterator
473 	//====================================================================
474     class DrawPageIterator
475     {
476     public:
477         DrawPageIterator( const Reference< XModel >& _rxDocument )
478             :m_xDocument( _rxDocument )
479             ,m_nPageCount( 0 )
480             ,m_nCurrentPage( 0 )
481         {
482             Reference< XDrawPageSupplier > xSingle( _rxDocument, UNO_QUERY );
483             Reference< XDrawPagesSupplier > xMulti( _rxDocument, UNO_QUERY );
484             if ( xSingle.is() )
485             {
486                 m_xSinglePage.set( xSingle->getDrawPage(), UNO_SET_THROW );
487                 m_nPageCount = 1;
488             }
489             else if ( xMulti.is() )
490             {
491                 m_xMultiPages.set( xMulti->getDrawPages(), UNO_SET_THROW );
492                 m_nPageCount = m_xMultiPages->getCount();
493             }
494         }
495 
496         bool hasMore() const
497         {
498             return m_nCurrentPage < m_nPageCount;
499         }
500 
501         Reference< XDrawPage > next()
502         {
503             Reference< XDrawPage > xNextPage;
504 
505             if ( m_xSinglePage.is() )
506             {
507                 xNextPage = m_xSinglePage;
508             }
509             else if ( m_xMultiPages.is() )
510             {
511                 xNextPage.set( m_xMultiPages->getByIndex( m_nCurrentPage ), UNO_QUERY_THROW );
512             }
513             ++m_nCurrentPage;
514             return xNextPage;
515         }
516 
517     private:
518         const Reference< XModel >   m_xDocument;
519         Reference< XDrawPage >      m_xSinglePage;
520         Reference< XDrawPages >     m_xMultiPages;
521         sal_Int32                   m_nPageCount;
522         sal_Int32                   m_nCurrentPage;
523     };
524 
525     //====================================================================
526 	//= FormComponentScripts
527 	//====================================================================
528     class FormComponentScripts
529     {
530     public:
531         FormComponentScripts(
532                 const Reference< XInterface >& _rxComponent,
533                 const Reference< XEventAttacherManager >& _rxManager,
534                 const sal_Int32 _nIndex
535             )
536             :m_xComponent( _rxComponent, UNO_SET_THROW )
537             ,m_xManager( _rxManager, UNO_SET_THROW )
538             ,m_nIndex( _nIndex )
539         {
540         }
541 
542         Sequence< ScriptEventDescriptor > getEvents() const
543         {
544             return m_xManager->getScriptEvents( m_nIndex );
545         }
546 
547         void setEvents( const Sequence< ScriptEventDescriptor >& _rEvents  ) const
548         {
549             m_xManager->registerScriptEvents( m_nIndex, _rEvents );
550         }
551 
552         const Reference< XInterface >& getComponent() const
553         {
554             return m_xComponent;
555         }
556 
557     private:
558         const Reference< XInterface >               m_xComponent;
559         const Reference< XEventAttacherManager >    m_xManager;
560         const sal_Int32                             m_nIndex;
561     };
562 
563     //====================================================================
564 	//= FormComponentIterator
565 	//====================================================================
566     class FormComponentIterator
567     {
568     public:
569         FormComponentIterator( const Reference< XIndexAccess >& _rxContainer )
570             :m_xContainer( _rxContainer, UNO_SET_THROW )
571             ,m_xEventManager( _rxContainer, UNO_QUERY_THROW )
572             ,m_nElementCount( _rxContainer->getCount() )
573             ,m_nCurrentElement( 0 )
574         {
575         }
576 
577         bool hasMore() const
578         {
579             return m_nCurrentElement < m_nElementCount;
580         }
581 
582         FormComponentScripts next()
583         {
584             FormComponentScripts aComponent(
585                 Reference< XInterface >( m_xContainer->getByIndex( m_nCurrentElement ), UNO_QUERY_THROW ),
586                 m_xEventManager,
587                 m_nCurrentElement
588             );
589             ++m_nCurrentElement;
590             return aComponent;
591         }
592 
593     private:
594         const Reference< XIndexAccess >             m_xContainer;
595         const Reference< XEventAttacherManager >    m_xEventManager;
596         const sal_Int32                             m_nElementCount;
597         sal_Int32                                   m_nCurrentElement;
598 
599     };
600 
601     //====================================================================
602 	//= ScriptsStorage - declaration
603 	//====================================================================
604     /** a helper class which encapsulates access to the storages for Java/Script, BeanShell, and Python scripts,
605         i.e. all script types which can be manipulated on storage level.
606     */
607     class ScriptsStorage
608     {
609     public:
610         ScriptsStorage( MigrationLog& _rLogger );
611         ScriptsStorage( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger );
612         ~ScriptsStorage();
613 
614         /** determines whether the instance is valid, i.e. refers to a valid root storage
615             for reading/storing scripts
616         */
617         inline bool isValid() const { return m_xScriptsStorage.is(); }
618 
619         /** binds the instance to a new document. Only to be called when the instance is not yet
620             bound (i.e. isValid returns <FALSE/>).
621         */
622         void    bind( const Reference< XModel >& _rxDocument );
623 
624         /// determines whether scripts of the given type are present
625         bool    hasScripts( const ScriptType _eType ) const;
626 
627         /// returns the root storage for the scripts of the given type
628         SharedStorage
629                 getScriptsRoot( const ScriptType _eType ) const;
630 
631         /** returns the names of the elements in the "Scripts" storage
632         */
633         ::std::set< ::rtl::OUString >
634                 getElementNames() const;
635 
636         /** removes the sub storage for a given script type
637             @precond
638                 the respective storage is empty
639             @precond
640                 the ScriptsStorage instance was opened for writing
641         */
642         void    removeScriptTypeStorage( const ScriptType _eType ) const;
643 
644         /** commits the changes at our XStorage object
645         */
646         bool    commit();
647 
648         /** removes the "Scripts" sub storage from the given document's root storage
649             @precond
650                 the "Scripts" storage is empty
651         */
652         static bool
653                 removeFromDocument( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger );
654 
655     private:
656         MigrationLog&   m_rLogger;
657         SharedStorage   m_xScriptsStorage;
658     };
659 
660     //====================================================================
661 	//= ScriptsStorage - implementation
662 	//====================================================================
663 	//--------------------------------------------------------------------
664     ScriptsStorage::ScriptsStorage( MigrationLog& _rLogger )
665         :m_rLogger( _rLogger )
666         ,m_xScriptsStorage()
667     {
668     }
669 
670 	//--------------------------------------------------------------------
671     ScriptsStorage::ScriptsStorage( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger )
672         :m_rLogger( _rLogger )
673         ,m_xScriptsStorage()
674     {
675         bind( _rxDocument );
676     }
677 
678 	//--------------------------------------------------------------------
679     ScriptsStorage::~ScriptsStorage()
680     {
681     }
682 
683     //--------------------------------------------------------------------
684     bool ScriptsStorage::commit()
685     {
686         return lcl_commitStorage_nothrow( m_xScriptsStorage );
687     }
688 
689 	//--------------------------------------------------------------------
690     void ScriptsStorage::bind( const Reference< XModel >& _rxDocument )
691     {
692         OSL_PRECOND( !isValid(), "ScriptsStorage:bind: did not bother, yet, to check whether this is allowed!" );
693         try
694         {
695             Reference< XStorageBasedDocument > xStorageDoc( _rxDocument, UNO_QUERY_THROW );
696             Reference< XStorage > xDocStorage( xStorageDoc->getDocumentStorage(), UNO_QUERY_THROW );
697 
698             // the the "Scripts" storage exist, or if it does not (yet) exist and we are in write mode
699             // => open the storage
700             if  (   (   xDocStorage->hasByName( lcl_getScriptsStorageName() )
701                     &&  xDocStorage->isStorageElement( lcl_getScriptsStorageName() )
702                     )
703                 ||  !xDocStorage->hasByName( lcl_getScriptsStorageName() )
704                 )
705             {
706                 m_xScriptsStorage.set(
707                     xDocStorage->openStorageElement(
708                         lcl_getScriptsStorageName(), ElementModes::READWRITE
709                     ),
710                     UNO_QUERY_THROW
711                 );
712             }
713         }
714         catch( const Exception& )
715         {
716             m_rLogger.logFailure( MigrationError(
717                 ERR_BIND_SCRIPT_STORAGE_FAILED,
718                 ::comphelper::DocumentInfo::getDocumentTitle( _rxDocument ),
719                 ::cppu::getCaughtException()
720             ) );
721         }
722     }
723 
724     //--------------------------------------------------------------------
725     bool ScriptsStorage::hasScripts( const ScriptType _eType ) const
726     {
727         OSL_PRECOND( isValid(), "ScriptsStorage::hasScripts: illegal call!" );
728         if ( !isValid() )
729             return false;
730 
731         const ::rtl::OUString& rSubStorageName( lcl_getScriptsSubStorageName( _eType ) );
732         return  m_xScriptsStorage->hasByName( rSubStorageName )
733             &&  m_xScriptsStorage->isStorageElement( rSubStorageName );
734     }
735 
736     //--------------------------------------------------------------------
737     SharedStorage ScriptsStorage::getScriptsRoot( const ScriptType _eType ) const
738     {
739         SharedStorage xStorage;
740         if ( isValid() )
741         {
742             xStorage.reset( m_xScriptsStorage->openStorageElement(
743                 lcl_getScriptsSubStorageName( _eType ), ElementModes::READWRITE
744             ) );
745         }
746         return xStorage;
747     }
748 
749     //--------------------------------------------------------------------
750     ::std::set< ::rtl::OUString > ScriptsStorage::getElementNames() const
751     {
752         Sequence< ::rtl::OUString > aElementNames;
753         if ( isValid() )
754             aElementNames = m_xScriptsStorage->getElementNames();
755 
756         ::std::set< ::rtl::OUString > aNames;
757         ::std::copy(
758             aElementNames.getConstArray(),
759             aElementNames.getConstArray() + aElementNames.getLength(),
760             ::std::insert_iterator< ::std::set< ::rtl::OUString > >( aNames, aNames.end() )
761         );
762         return aNames;
763     }
764 
765     //--------------------------------------------------------------------
766     void ScriptsStorage::removeScriptTypeStorage( const ScriptType _eType ) const
767     {
768         ::rtl::OUString sSubStorageName( lcl_getScriptsSubStorageName( _eType ) );
769         if ( m_xScriptsStorage->hasByName( sSubStorageName ) )
770             m_xScriptsStorage->removeElement( sSubStorageName );
771     }
772 
773     //--------------------------------------------------------------------
774     bool ScriptsStorage::removeFromDocument( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger )
775     {
776         try
777         {
778             Reference< XStorageBasedDocument > xStorageDoc( _rxDocument, UNO_QUERY_THROW );
779             Reference< XStorage > xDocStorage( xStorageDoc->getDocumentStorage(), UNO_QUERY_THROW );
780             xDocStorage->removeElement( lcl_getScriptsStorageName() );
781         }
782         catch( const Exception& )
783         {
784             _rLogger.logFailure( MigrationError(
785                 ERR_REMOVE_SCRIPTS_STORAGE_FAILED,
786                 ::comphelper::DocumentInfo::getDocumentTitle( _rxDocument ),
787                 ::cppu::getCaughtException()
788             ) ) ;
789             return false;
790         }
791         return true;
792     }
793 
794     //====================================================================
795     //= ProgressDelegator
796     //====================================================================
797     class ProgressDelegator : public IProgressConsumer
798     {
799     public:
800         ProgressDelegator(  IMigrationProgress& _rDelegator,
801                             const ::rtl::OUString& _rObjectName,
802                             const ::rtl::OUString& _rAction
803                           )
804             :m_rDelegator( _rDelegator )
805             ,m_sObjectName( _rObjectName )
806             ,m_sAction( _rAction )
807         {
808         }
809         virtual ~ProgressDelegator()
810         {
811         }
812 
813         // IProgressConsumer
814         virtual void    start( sal_uInt32 _nRange )
815         {
816             m_rDelegator.startObject( m_sObjectName, m_sAction, _nRange );
817         }
818         virtual void    advance( sal_uInt32 _nValue )
819         {
820             m_rDelegator.setObjectProgressValue( _nValue );
821         }
822         virtual void    end()
823         {
824             m_rDelegator.endObject();
825         }
826 
827     private:
828         IMigrationProgress& m_rDelegator;
829         ::rtl::OUString     m_sObjectName;
830         ::rtl::OUString     m_sAction;
831     };
832 
833 	//====================================================================
834 	//= PhaseGuard
835 	//====================================================================
836     class PhaseGuard
837     {
838     public:
839         PhaseGuard( ProgressMixer& _rMixer )
840             :m_rMixer( _rMixer )
841         {
842         }
843 
844         PhaseGuard( ProgressMixer& _rMixer, const PhaseID _nID, const sal_uInt32 _nPhaseRange )
845             :m_rMixer( _rMixer )
846         {
847             start( _nID, _nPhaseRange );
848         }
849 
850         ~PhaseGuard()
851         {
852             m_rMixer.endPhase();
853         }
854 
855         void start( const PhaseID _nID, const sal_uInt32 _nPhaseRange )
856         {
857             m_rMixer.startPhase( _nID, _nPhaseRange );
858         }
859 
860     private:
861         ProgressMixer&  m_rMixer;
862     };
863 
864 	//====================================================================
865 	//= MigrationEngine_Impl - declaration
866 	//====================================================================
867     class MigrationEngine_Impl
868     {
869     public:
870         MigrationEngine_Impl(
871             const ::comphelper::ComponentContext& _rContext,
872             const Reference< XOfficeDatabaseDocument >& _rxDocument,
873             IMigrationProgress& _rProgress,
874             MigrationLog& _rLogger
875         );
876         ~MigrationEngine_Impl();
877 
878         inline  size_t      getFormCount() const    { return m_nFormCount; }
879         inline  size_t      getReportCount()const   { return m_nReportCount; }
880         bool    migrateAll();
881 
882     private:
883         ::comphelper::ComponentContext              m_aContext;
884         const Reference< XOfficeDatabaseDocument >  m_xDocument;
885         const Reference< XModel >                   m_xDocumentModel;
886         IMigrationProgress&                         m_rProgress;
887         MigrationLog&                               m_rLogger;
888         mutable DocumentID                          m_nCurrentDocumentID;
889         SubDocuments                                m_aSubDocs;
890         size_t                                      m_nFormCount;
891         size_t                                      m_nReportCount;
892 
893     private:
894         /** collects a description of all sub documents of our database document
895 
896             @return
897                 <TRUE/> if and only if collecting the documents was successful
898         */
899         bool    impl_collectSubDocuments_nothrow();
900 
901         /** migrates the macros/scripts of the given sub document
902         */
903         bool    impl_handleDocument_nothrow( const SubDocument& _rDocument ) const;
904 
905         /** checks the structure of the 'Scripts' folder of a sub document
906             for unknown elements
907 
908             @return
909                 <TRUE/> if and only if the 'Scripts' folder contains known elements only.
910         */
911         bool    impl_checkScriptStorageStructure_nothrow( const SubDocument& _rDocument ) const;
912 
913         /** migrates the scripts of the given "storage-based" script type
914         */
915         bool    impl_migrateScriptStorage_nothrow(
916                     const SubDocument& _rDocument,
917                     const ScriptType _eScriptType,
918                     ProgressMixer& _rProgress,
919                     const PhaseID _nPhaseID
920                 ) const;
921 
922         /** migrates the content of the given "container based" libraries (Basic/Dialogs)
923         */
924         bool    impl_migrateContainerLibraries_nothrow(
925                     const SubDocument& _rDocument,
926                     const ScriptType _eScriptType,
927                     ProgressMixer& _rProgress,
928                     const PhaseID _nPhaseID
929                 ) const;
930 
931         /** adjusts the events for the given dialog/element, taking into account the new names
932             of the moved libraries
933         */
934         void    impl_adjustDialogElementEvents_throw(
935                     const Reference< XInterface >& _rxElement
936                 ) const;
937 
938         /** adjusts the events in the given dialog, and its controls, taking into account the new names
939             of the moved libraries
940         */
941         bool    impl_adjustDialogEvents_nothrow(
942                     Any& _inout_rDialogLibraryElement,
943                     const ::rtl::OUString& _rDocName,
944                     const ::rtl::OUString& _rDialogLibName,
945                     const ::rtl::OUString& _rDialogName
946                 ) const;
947 
948         /** adjust the document-events which refer to macros/scripts in the document, taking into
949             account the new names of the moved libraries
950         */
951         bool    impl_adjustDocumentEvents_nothrow(
952                     const SubDocument& _rDocument
953                 ) const;
954 
955         /** adjusts the script references bound to form component events
956         */
957         bool    impl_adjustFormComponentEvents_nothrow(
958                     const SubDocument& _rDocument
959                 ) const;
960 
961         /** adjusts the script references for the elements of the given form component container
962         */
963         void    impl_adjustFormComponentEvents_throw(
964                     const Reference< XIndexAccess >& _rxComponentContainer
965                 ) const;
966 
967         /** adjusts the library name in the given script URL, so that it reflects
968             the new name of the library
969 
970             @return <TRUE/>
971                 if and only if adjustments to the script code have been made
972         */
973         bool    impl_adjustScriptLibrary_nothrow(
974                     const ::rtl::OUString& _rScriptType,
975                     ::rtl::OUString& _inout_rScriptCode
976                 ) const;
977 
978         bool    impl_adjustScriptLibrary_nothrow( Any& _inout_rScriptDescriptor ) const;
979         bool    impl_adjustScriptLibrary_nothrow( ScriptEventDescriptor& _inout_rScriptEvent ) const;
980 
981         /** asks the user for a password for the given library, and unprotects the library
982 
983             @return <TRUE/>
984                 if and only if the library could be successfully unprotected
985         */
986         bool    impl_unprotectPasswordLibrary_throw(
987                     const Reference< XLibraryContainerPassword >& _rxPasswordManager,
988                     const ScriptType _eScriptType,
989                     const ::rtl::OUString& _rLibraryName
990                 ) const;
991     };
992 
993 	//====================================================================
994 	//= MigrationEngine_Impl - implementation
995 	//====================================================================
996 	//--------------------------------------------------------------------
997     MigrationEngine_Impl::MigrationEngine_Impl( const ::comphelper::ComponentContext& _rContext,
998             const Reference< XOfficeDatabaseDocument >& _rxDocument, IMigrationProgress& _rProgress, MigrationLog& _rLogger )
999         :m_aContext( _rContext )
1000         ,m_xDocument( _rxDocument )
1001         ,m_xDocumentModel( _rxDocument, UNO_QUERY_THROW )
1002         ,m_rProgress( _rProgress )
1003         ,m_rLogger( _rLogger )
1004         ,m_nCurrentDocumentID( - 1 )
1005         ,m_aSubDocs()
1006         ,m_nFormCount( 0 )
1007         ,m_nReportCount( 0 )
1008     {
1009         OSL_VERIFY( impl_collectSubDocuments_nothrow() );
1010     }
1011 
1012 	//--------------------------------------------------------------------
1013     MigrationEngine_Impl::~MigrationEngine_Impl()
1014     {
1015     }
1016 
1017 	//--------------------------------------------------------------------
1018     bool MigrationEngine_Impl::migrateAll()
1019     {
1020         if  ( m_aSubDocs.empty() )
1021         {
1022             OSL_ENSURE( false, "MigrationEngine_Impl::migrateAll: no forms/reports found!" );
1023             // The whole migration wizard is not expected to be called when there are no forms/reports
1024             // with macros, not to mention when there are no forms/reports at all.
1025             return false;
1026         }
1027 
1028         // initialize global progress
1029         sal_Int32 nOverallRange( m_aSubDocs.size() );
1030         String sProgressSkeleton = String( MacroMigrationResId( STR_OVERALL_PROGRESS ) );
1031         sProgressSkeleton.SearchAndReplaceAscii( "$overall$", String::CreateFromInt32( nOverallRange ) );
1032 
1033         m_rProgress.start( nOverallRange );
1034 
1035         for (   SubDocuments::const_iterator doc = m_aSubDocs.begin();
1036                 doc != m_aSubDocs.end();
1037                 ++doc
1038             )
1039         {
1040             sal_Int32 nOverallProgressValue( doc - m_aSubDocs.begin() + 1 );
1041             // update overall progress text
1042             ::rtl::OUString sOverallProgress( sProgressSkeleton );
1043             ::comphelper::string::searchAndReplaceAsciiI( sOverallProgress, "$current$", ::rtl::OUString::valueOf( nOverallProgressValue ) );
1044             m_rProgress.setOverallProgressText( sOverallProgress );
1045 
1046             // migrate document
1047             if ( !impl_handleDocument_nothrow( *doc ) )
1048                 return false;
1049 
1050             // update overall progress vallue
1051             m_rProgress.setOverallProgressValue( nOverallProgressValue );
1052         }
1053 
1054         // commit the root storage of the database document, for all changes made so far to take effect
1055         if ( !lcl_commitDocumentStorage_nothrow( m_xDocumentModel, m_rLogger ) )
1056             return false;
1057 
1058         // save the document
1059         if ( !lcl_storeDocument_nothrow( m_xDocumentModel, m_rLogger ) )
1060             return false;
1061 
1062         return true;
1063     }
1064 
1065 	//--------------------------------------------------------------------
1066     namespace
1067     {
1068         void lcl_collectHierarchicalElementNames_throw(
1069             const Reference< XNameAccess >& _rxContainer, const ::rtl::OUString& _rContainerLoc,
1070             SubDocuments& _out_rDocs, const SubDocumentType _eType, size_t& _io_counter )
1071         {
1072             const ::rtl::OUString sHierarhicalBase(
1073                 _rContainerLoc.getLength()  ?   ::rtl::OUStringBuffer( _rContainerLoc ).appendAscii( "/" ).makeStringAndClear()
1074                                             :   ::rtl::OUString() );
1075 
1076             Sequence< ::rtl::OUString > aElementNames( _rxContainer->getElementNames() );
1077             for (   const ::rtl::OUString* elementName = aElementNames.getConstArray();
1078                     elementName != aElementNames.getConstArray() + aElementNames.getLength();
1079                     ++elementName
1080                 )
1081             {
1082                 Any aElement( _rxContainer->getByName( *elementName ) );
1083                 ::rtl::OUString sElementName( ::rtl::OUStringBuffer( sHierarhicalBase ).append( *elementName ) );
1084 
1085                 Reference< XNameAccess > xSubContainer( aElement, UNO_QUERY );
1086                 if ( xSubContainer.is() )
1087                 {
1088                     lcl_collectHierarchicalElementNames_throw( xSubContainer, sElementName, _out_rDocs, _eType, _io_counter );
1089                 }
1090                 else
1091                 {
1092                     Reference< XCommandProcessor > xCommandProcessor( aElement, UNO_QUERY );
1093                     OSL_ENSURE( xCommandProcessor.is(), "lcl_collectHierarchicalElementNames_throw: no container, and no comand processor? What *is* it, then?!" );
1094                     if ( xCommandProcessor.is() )
1095                     {
1096                         _out_rDocs.push_back( SubDocument( xCommandProcessor, sElementName, _eType, ++_io_counter ) );
1097                     }
1098                 }
1099             }
1100         }
1101     }
1102 
1103     //--------------------------------------------------------------------
1104     bool MigrationEngine_Impl::impl_collectSubDocuments_nothrow()
1105     {
1106         OSL_PRECOND( m_xDocument.is(), "MigrationEngine_Impl::impl_collectSubDocuments_nothrow: invalid document!" );
1107         if ( !m_xDocument.is() )
1108             return false;
1109 
1110         try
1111         {
1112             Reference< XNameAccess > xDocContainer( m_xDocument->getFormDocuments(), UNO_SET_THROW );
1113             m_nFormCount = 0;
1114             lcl_collectHierarchicalElementNames_throw( xDocContainer, ::rtl::OUString(), m_aSubDocs, eForm, m_nFormCount );
1115 
1116             xDocContainer.set( m_xDocument->getReportDocuments(), UNO_SET_THROW );
1117             m_nReportCount = 0;
1118             lcl_collectHierarchicalElementNames_throw( xDocContainer, ::rtl::OUString(), m_aSubDocs, eReport, m_nReportCount );
1119         }
1120         catch( const Exception& )
1121         {
1122             m_rLogger.logFailure( MigrationError(
1123                 ERR_COLLECTING_DOCUMENTS_FAILED,
1124                 ::cppu::getCaughtException()
1125             ) );
1126             return false;
1127         }
1128         return true;
1129     }
1130 
1131 	//--------------------------------------------------------------------
1132     bool MigrationEngine_Impl::impl_handleDocument_nothrow( const SubDocument& _rDocument ) const
1133     {
1134         OSL_ENSURE( m_nCurrentDocumentID == -1,
1135             "MigrationEngine_Impl::impl_handleDocument_nothrow: there already is a current document!");
1136         m_nCurrentDocumentID = m_rLogger.startedDocument( _rDocument.eType, _rDocument.sHierarchicalName );
1137 
1138         // start the progress
1139         ::rtl::OUString sObjectName( lcl_getSubDocumentDescription( _rDocument ) );
1140         m_rProgress.startObject( sObjectName, ::rtl::OUString(), DEFAULT_DOC_PROGRESS_RANGE );
1141 
1142         // -----------------
1143         // load the document
1144         ::rtl::Reference< ProgressCapture > pStatusIndicator( new ProgressCapture( sObjectName, m_rProgress ) );
1145         SubDocument aSubDocument( _rDocument );
1146         OpenDocResult eResult = lcl_loadSubDocument_nothrow( aSubDocument, pStatusIndicator.get(), m_rLogger );
1147         if ( eResult != eOpenedDoc )
1148         {
1149             pStatusIndicator->dispose();
1150             m_rProgress.endObject();
1151             m_rLogger.finishedDocument( m_nCurrentDocumentID );
1152 			m_nCurrentDocumentID = -1;
1153             return ( eResult == eIgnoreDoc );
1154         }
1155 
1156         // -----------------
1157         // migrate the libraries
1158         ProgressDelegator aDelegator( m_rProgress, sObjectName, String( MacroMigrationResId( STR_MIGRATING_LIBS ) ) );
1159         ProgressMixer aProgressMixer( aDelegator );
1160         aProgressMixer.registerPhase( PHASE_JAVASCRIPT, 1 );
1161         aProgressMixer.registerPhase( PHASE_BEANSHELL, 1 );
1162         aProgressMixer.registerPhase( PHASE_PYTHON, 1 );
1163         aProgressMixer.registerPhase( PHASE_JAVA, 1 );
1164         aProgressMixer.registerPhase( PHASE_BASIC, 5 );
1165             // more weight than then others, assuming that usually, there are much more Basic macros than any other scripts
1166         aProgressMixer.registerPhase( PHASE_DIALOGS, 1 );
1167 
1168         bool bSuccess = impl_checkScriptStorageStructure_nothrow( aSubDocument );
1169 
1170         // migrate storage-based script libraries (which can be handled by mere storage operations)
1171         bSuccess = bSuccess
1172             &&  impl_migrateScriptStorage_nothrow( aSubDocument, eJavaScript, aProgressMixer, PHASE_JAVASCRIPT )
1173             &&  impl_migrateScriptStorage_nothrow( aSubDocument, eBeanShell, aProgressMixer, PHASE_BEANSHELL )
1174             &&  impl_migrateScriptStorage_nothrow( aSubDocument, ePython, aProgressMixer, PHASE_PYTHON )
1175             &&  impl_migrateScriptStorage_nothrow( aSubDocument, eJava, aProgressMixer, PHASE_JAVA );
1176 
1177         // migrate Basic and dialog libraries
1178         bSuccess =  bSuccess
1179                 &&  impl_migrateContainerLibraries_nothrow( aSubDocument, eBasic, aProgressMixer, PHASE_BASIC )
1180                 &&  impl_migrateContainerLibraries_nothrow( aSubDocument, eDialog, aProgressMixer, PHASE_DIALOGS );
1181                 // order matters: First Basic scripts, then dialogs. So we can adjust references from the latter
1182                 // to the former
1183 
1184         // adjust the events in the document
1185         // (note that errors are ignored here - failure to convert a script reference
1186         // is not considered a critical error)
1187         if ( bSuccess )
1188         {
1189             impl_adjustDocumentEvents_nothrow( aSubDocument );
1190             impl_adjustFormComponentEvents_nothrow( aSubDocument );
1191         }
1192 
1193         // -----------------
1194         // clean up
1195         // store the sub document, including removal of the (now obsolete) "Scripts" sub folder
1196         if ( m_rLogger.movedAnyLibrary( m_nCurrentDocumentID ) )
1197         {
1198             bSuccess =  bSuccess
1199                     &&  ScriptsStorage::removeFromDocument( aSubDocument.xDocument, m_rLogger )
1200                     &&  lcl_commitDocumentStorage_nothrow( aSubDocument.xDocument, m_rLogger )
1201                     &&  lcl_storeEmbeddedDocument_nothrow( aSubDocument );
1202         }
1203 
1204         // unload in any case, even if we were not successful
1205         bSuccess =  lcl_unloadSubDocument_nothrow( aSubDocument, m_rLogger )
1206                 &&  bSuccess;
1207 
1208         pStatusIndicator->dispose();
1209 
1210         // end the progress, just in case the ProgressCapture didn't receive the XStatusIndicator::end event
1211         m_rProgress.endObject();
1212 
1213         m_rLogger.finishedDocument( m_nCurrentDocumentID );
1214         m_nCurrentDocumentID = -1;
1215         return bSuccess;
1216     }
1217 
1218 	//--------------------------------------------------------------------
1219     namespace
1220     {
1221         static ::rtl::OUString lcl_createTargetLibName( const SubDocument& _rDocument,
1222             const ::rtl::OUString& _rSourceLibName, const Reference< XNameAccess >& _rxTargetContainer )
1223         {
1224             // The new library name is composed from the prefix, the base name, and the old library name.
1225             const ::rtl::OUString sPrefix( ::rtl::OUString::createFromAscii( _rDocument.eType == eForm ? "Form_" : "Report_" ) );
1226 
1227             ::rtl::OUString sBaseName( _rDocument.sHierarchicalName.copy(
1228                 _rDocument.sHierarchicalName.lastIndexOf( '/' ) + 1 ) );
1229             // Normalize this name. In our current storage implementation (and script containers in a document
1230             // are finally mapped to sub storages of the document storage), not all characters are allowed.
1231             // The bug requesting to change this is #i95409#.
1232             // Unfortunately, the storage implementation does not complain if you use invalid characters/names, but instead
1233             // it silently accepts them, and produces garbage in the file (#i95408).
1234             // So, until especially the former is fixed, we need to strip the name from all invalid characters.
1235             // #i95865# / 2008-11-06 / frank.schoenheit@sun.com
1236 
1237             // The general idea is to replace invalid characters with '_'. However, since "valid" essentially means
1238             // ASCII only, this implies that for a lot of languages, we would simply replace everything with '_',
1239             // which of course is not desired.
1240             // So, we use a heuristics: If the name contains at most 3 invalid characters, and as many valid as invalid
1241             // characters, then we use the replacement. Otherwise, we just use a unambiguous number for the sub document.
1242             sal_Int32 nValid=0, nInvalid=0;
1243             const sal_Unicode* pBaseName = sBaseName.getStr();
1244             const sal_Int32 nBaseNameLen = sBaseName.getLength();
1245             for ( sal_Int32 i=0; i<nBaseNameLen; ++i )
1246             {
1247                 if ( ::comphelper::OStorageHelper::IsValidZipEntryFileName( pBaseName + i, 1, sal_False ) )
1248                     ++nValid;
1249                 else
1250                     ++nInvalid;
1251             }
1252             if ( ( nInvalid <= 3 ) && ( nInvalid * 2 <= nValid ) )
1253             {   // not "too many" invalid => replace them
1254                 ::rtl::OUStringBuffer aReplacement;
1255                 aReplacement.ensureCapacity( nBaseNameLen );
1256                 aReplacement.append( sBaseName );
1257                 const sal_Unicode* pReplacement = aReplacement.getStr();
1258                 for ( sal_Int32 i=0; i<nBaseNameLen; ++i )
1259                 {
1260                     if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( pReplacement + i, 1, sal_False ) )
1261                         aReplacement.setCharAt( i, '_' );
1262                 }
1263                 sBaseName = aReplacement.makeStringAndClear();
1264 
1265                 ::rtl::OUStringBuffer aNewLibNameAttempt;
1266                 aNewLibNameAttempt.append( sPrefix );
1267                 aNewLibNameAttempt.append( sBaseName );
1268                 aNewLibNameAttempt.appendAscii( "_" );
1269                 aNewLibNameAttempt.append( _rSourceLibName );
1270                 ::rtl::OUString sTargetName( aNewLibNameAttempt.makeStringAndClear() );
1271                 if ( !_rxTargetContainer->hasByName( sTargetName ) )
1272                     return sTargetName;
1273             }
1274 
1275             // "too many" invalid characters, or the name composed with the base name was already used.
1276             // (The latter is valid, since there can be multiple sub documents with the same base name,
1277             // in different levels in the hierarchy.)
1278             // In this case, just use the umambiguous sub document number.
1279             ::rtl::OUStringBuffer aNewLibName;
1280             aNewLibName.append( sPrefix );
1281             aNewLibName.append( ::rtl::OUString::valueOf( sal_Int64( _rDocument.nNumber ) ) );
1282             aNewLibName.appendAscii( "_" );
1283             aNewLibName.append( _rSourceLibName );
1284             return aNewLibName.makeStringAndClear();
1285         }
1286     }
1287 
1288     //--------------------------------------------------------------------
1289     bool MigrationEngine_Impl::impl_checkScriptStorageStructure_nothrow( const SubDocument& _rDocument ) const
1290     {
1291         OSL_PRECOND( _rDocument.xDocument.is(), "MigrationEngine_Impl::impl_checkScriptStorageStructure_nothrow: invalid document!" );
1292         if ( !_rDocument.xDocument.is() )
1293             return false;
1294 
1295         try
1296         {
1297             // the root storage of the document whose scripts are to be migrated
1298             ScriptsStorage aDocStorage( _rDocument.xDocument, m_rLogger );
1299             if  ( !aDocStorage.isValid() )
1300             {   // no scripts at all, or no scripts of the given type
1301                 return !m_rLogger.hadFailure();
1302             }
1303             ::std::set< ::rtl::OUString > aElementNames( aDocStorage.getElementNames() );
1304 
1305             ScriptType aKnownStorageBasedTypes[] = {
1306                 eBeanShell, eJavaScript, ePython, eJava
1307             };
1308             for ( size_t i=0; i<sizeof( aKnownStorageBasedTypes ) / sizeof( aKnownStorageBasedTypes[0] ); ++i )
1309                 aElementNames.erase( lcl_getScriptsSubStorageName( aKnownStorageBasedTypes[i] ) );
1310 
1311             if ( !aElementNames.empty() )
1312             {
1313                 m_rLogger.logFailure( MigrationError(
1314                     ERR_UNKNOWN_SCRIPT_FOLDER,
1315                     lcl_getSubDocumentDescription( _rDocument ),
1316                     *aElementNames.begin()
1317                 ) );
1318                 return false;
1319             }
1320         }
1321         catch( const Exception& )
1322         {
1323             m_rLogger.logFailure( MigrationError(
1324                 ERR_EXAMINING_SCRIPTS_FOLDER_FAILED,
1325                 lcl_getSubDocumentDescription( _rDocument ),
1326                 ::cppu::getCaughtException()
1327             ) );
1328             return false;
1329         }
1330         return true;
1331     }
1332 
1333     //--------------------------------------------------------------------
1334     bool MigrationEngine_Impl::impl_migrateScriptStorage_nothrow( const SubDocument& _rDocument,
1335         const ScriptType _eScriptType, ProgressMixer& _rProgress, const PhaseID _nPhaseID ) const
1336     {
1337         OSL_PRECOND( _rDocument.xDocument.is(), "MigrationEngine_Impl::impl_migrateScriptStorage_nothrow: invalid document!" );
1338         if ( !_rDocument.xDocument.is() )
1339             return false;
1340 
1341         ScriptsStorage aDatabaseScripts( m_rLogger );
1342             // the scripts of our complete database document - created on demand only
1343         SharedStorage xTargetStorage;
1344             // the target for moving the scripts storages - created on demand only
1345 
1346         PhaseGuard aPhase( _rProgress );
1347         bool bSuccess = false;
1348         Any aException;
1349         try
1350         {
1351             // the root storage of the document whose scripts are to be migrated
1352             ScriptsStorage aDocStorage( _rDocument.xDocument, m_rLogger );
1353             if  (   !aDocStorage.isValid()
1354                 ||  !aDocStorage.hasScripts( _eScriptType )
1355                 )
1356             {
1357                 // no scripts at all, or no scripts of the given type
1358                 _rProgress.startPhase( _nPhaseID, 1 );
1359                 _rProgress.endPhase();
1360                 return !m_rLogger.hadFailure();
1361             }
1362 
1363             SharedStorage xScriptsRoot( aDocStorage.getScriptsRoot( _eScriptType ) );
1364             if ( !xScriptsRoot.is() )
1365                 throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "internal error" ) ), NULL );
1366 
1367             // loop through the script libraries
1368             Sequence< ::rtl::OUString > aStorageElements( xScriptsRoot->getElementNames() );
1369             aPhase.start( _nPhaseID, aStorageElements.getLength() );
1370 
1371             for (   const ::rtl::OUString* element = aStorageElements.getConstArray();
1372                     element != aStorageElements.getConstArray() + aStorageElements.getLength();
1373                     ++element
1374                 )
1375             {
1376                 bool bIsScriptLibrary = xScriptsRoot->isStorageElement( *element );
1377                 OSL_ENSURE( bIsScriptLibrary,
1378                     "MigrationEngine_Impl::impl_migrateScriptStorage_nothrow: warning: unknown scripts storage structure!" );
1379                     // we cannot handle this. We would need to copy this stream to the respective scripts storage
1380                     // of the database document, but we cannot guarantee that the name is not used, yet, and we cannot
1381                     // simply rename the thing.
1382                 if ( !bIsScriptLibrary )
1383                 {
1384                     m_rLogger.logFailure( MigrationError(
1385                         ERR_UNEXPECTED_LIBSTORAGE_ELEMENT,
1386                         lcl_getSubDocumentDescription( _rDocument ),
1387                         getScriptTypeDisplayName( _eScriptType ),
1388                         *element
1389                     ) );
1390                     return false;
1391                 }
1392 
1393                 // ensure we have access to the DBDoc's scripts storage
1394                 if ( !aDatabaseScripts.isValid() )
1395                 {   // not needed 'til now
1396                     aDatabaseScripts.bind( m_xDocumentModel );
1397                     if ( aDatabaseScripts.isValid() )
1398                         xTargetStorage = aDatabaseScripts.getScriptsRoot( _eScriptType );
1399 
1400                     if ( !xTargetStorage.is() )
1401                     {
1402                         m_rLogger.logFailure( MigrationError(
1403                             ERR_CREATING_DBDOC_SCRIPT_STORAGE_FAILED,
1404                             getScriptTypeDisplayName( _eScriptType )
1405                         ) );
1406                         return false;
1407                     }
1408                 }
1409 
1410                 // move the library to the DBDoc's scripts library, under the new name
1411                 ::rtl::OUString sNewLibName( lcl_createTargetLibName( _rDocument, *element, xTargetStorage.getTyped().get() ) );
1412                 xScriptsRoot->moveElementTo( *element, xTargetStorage, sNewLibName );
1413 
1414                 // log the fact that we moved the library
1415                 m_rLogger.movedLibrary( m_nCurrentDocumentID, _eScriptType, *element, sNewLibName );
1416 
1417                 // progress
1418                 _rProgress.advancePhase( element - aStorageElements.getConstArray() );
1419             }
1420 
1421             // commit the storages, so the changes we made persist
1422             if  (   !lcl_commitStorage_nothrow( xScriptsRoot )
1423                 ||  ( xTargetStorage.is() && !lcl_commitStorage_nothrow( xTargetStorage ) )
1424                 )
1425             {
1426                 m_rLogger.logFailure( MigrationError(
1427                     ERR_COMMITTING_SCRIPT_STORAGES_FAILED,
1428                     getScriptTypeDisplayName( _eScriptType ),
1429                     lcl_getSubDocumentDescription( _rDocument )
1430                 ) );
1431                 return false;
1432             }
1433 
1434             // now that the concrete scripts storage does not have any elements anymore,
1435             // remove it
1436             xScriptsRoot.reset( NULL ); // need to reset the storage to be allowed to remove it
1437             aDocStorage.removeScriptTypeStorage( _eScriptType );
1438 
1439             // done so far
1440             bSuccess =  aDocStorage.commit()
1441                     &&  aDatabaseScripts.commit();
1442         }
1443         catch( const Exception& )
1444         {
1445             aException = ::cppu::getCaughtException();
1446             bSuccess = false;
1447         }
1448 
1449         // log the error, if any
1450         if ( !bSuccess )
1451         {
1452             m_rLogger.logFailure( MigrationError(
1453                 ERR_GENERAL_SCRIPT_MIGRATION_FAILURE,
1454                 getScriptTypeDisplayName( _eScriptType ),
1455                 lcl_getSubDocumentDescription( _rDocument ),
1456                 aException
1457             ) );
1458         }
1459 
1460         return bSuccess;
1461     }
1462 
1463 	//--------------------------------------------------------------------
1464     bool MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow( const SubDocument& _rDocument,
1465             const ScriptType _eScriptType, ProgressMixer& _rProgress, const PhaseID _nPhaseID ) const
1466     {
1467 		OSL_PRECOND( ( _eScriptType == eBasic ) || ( _eScriptType == eDialog ),
1468             "MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow: illegal script type!" );
1469 
1470         bool bSuccess = false;
1471         PhaseGuard aPhase( _rProgress );
1472         Any aException;
1473         do  // artificial loop for flow control only
1474         {
1475         try
1476         {
1477             // access library container of the sub document
1478             Reference< XEmbeddedScripts > xSubDocScripts( _rDocument.xDocument, UNO_QUERY );
1479             if ( !xSubDocScripts.is() )
1480             {   // no script support in the sub document -> nothing to migrate
1481                 // (though ... this is suspicious, at least ...)
1482                 bSuccess = true;
1483                 break;
1484             }
1485 
1486             Reference< XStorageBasedLibraryContainer > xSourceLibraries(
1487                 _eScriptType == eBasic ? xSubDocScripts->getBasicLibraries() : xSubDocScripts->getDialogLibraries(),
1488                 UNO_QUERY_THROW
1489             );
1490             Reference< XLibraryContainerPassword > xSourcePasswords( xSourceLibraries, UNO_QUERY );
1491             OSL_ENSURE( xSourcePasswords.is(),
1492                 "MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow: suspicious: no password management for the source libraries!" );
1493 
1494             Sequence< ::rtl::OUString > aSourceLibNames( xSourceLibraries->getElementNames() );
1495             aPhase.start( _nPhaseID, aSourceLibNames.getLength() );
1496 
1497             if ( !xSourceLibraries->hasElements() )
1498             {
1499                 bSuccess = true;
1500                 break;
1501             }
1502 
1503             // create library containers for the document - those will be the target for the migration
1504             Reference< XStorageBasedDocument > xStorageDoc( m_xDocument, UNO_QUERY_THROW );
1505             Reference< XStorageBasedLibraryContainer > xTargetLibraries;
1506             if ( _eScriptType == eBasic )
1507             {
1508                 xTargetLibraries.set( DocumentScriptLibraryContainer::create(
1509                     m_aContext.getUNOContext(), xStorageDoc ), UNO_QUERY_THROW );
1510             }
1511             else
1512             {
1513                 xTargetLibraries.set( DocumentDialogLibraryContainer::create(
1514                     m_aContext.getUNOContext(), xStorageDoc ), UNO_QUERY_THROW );
1515             }
1516 
1517             // copy all libs to the target, with potentially renaming them
1518             const ::rtl::OUString* pSourceLibBegin = aSourceLibNames.getConstArray();
1519             const ::rtl::OUString* pSourceLibEnd = pSourceLibBegin + aSourceLibNames.getLength();
1520             for (   const ::rtl::OUString* pSourceLibName = pSourceLibBegin;
1521                     pSourceLibName != pSourceLibEnd;
1522                     ++pSourceLibName
1523                 )
1524             {
1525                 // if the library is password-protected, ask the user to unprotect it
1526                 if  (   xSourcePasswords.is()
1527                     &&  xSourcePasswords->isLibraryPasswordProtected( *pSourceLibName )
1528                     &&  !xSourcePasswords->isLibraryPasswordVerified( *pSourceLibName )
1529                     )
1530                 {
1531                     if ( !impl_unprotectPasswordLibrary_throw( xSourcePasswords, _eScriptType, *pSourceLibName ) )
1532                     {
1533                         m_rLogger.logFailure( MigrationError(
1534                             ERR_PASSWORD_VERIFICATION_FAILED,
1535                             _rDocument.sHierarchicalName,
1536                             getScriptTypeDisplayName( _eScriptType ),
1537                             *pSourceLibName
1538                         ) );
1539                         return false;
1540                     }
1541                 }
1542 
1543                 ::rtl::OUString sNewLibName( lcl_createTargetLibName( _rDocument, *pSourceLibName, xTargetLibraries.get() ) );
1544 
1545                 if ( xSourceLibraries->isLibraryLink( *pSourceLibName ) )
1546                 {
1547                     // just re-create the link in the target library
1548                     xTargetLibraries->createLibraryLink(
1549                         sNewLibName,
1550                         xSourceLibraries->getLibraryLinkURL( *pSourceLibName ),
1551                         xSourceLibraries->isLibraryReadOnly( *pSourceLibName )
1552                     );
1553                 }
1554                 else
1555                 {
1556                     if ( !xSourceLibraries->isLibraryLoaded( *pSourceLibName ) )
1557                         xSourceLibraries->loadLibrary( *pSourceLibName );
1558 
1559                     // copy the content of this particular libary
1560                     Reference< XNameAccess > xSourceLib( xSourceLibraries->getByName( *pSourceLibName ), UNO_QUERY_THROW );
1561                     Reference< XNameContainer > xTargetLib( xTargetLibraries->createLibrary( sNewLibName ), UNO_QUERY_THROW );
1562 
1563                     Sequence< ::rtl::OUString > aLibElementNames( xSourceLib->getElementNames() );
1564                     for (   const ::rtl::OUString* pSourceElementName = aLibElementNames.getConstArray();
1565                             pSourceElementName != aLibElementNames.getConstArray() + aLibElementNames.getLength();
1566                             ++pSourceElementName
1567                         )
1568                     {
1569                         Any aElement = xSourceLib->getByName( *pSourceElementName );
1570                         OSL_ENSURE( aElement.hasValue(),
1571                             "MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow: invalid (empty) lib element!" );
1572 
1573                         // if this is a dialog, adjust the references to scripts
1574                         if ( _eScriptType == eDialog )
1575                         {
1576                             impl_adjustDialogEvents_nothrow( aElement, lcl_getSubDocumentDescription( _rDocument ),
1577                                 *pSourceLibName, *pSourceElementName );
1578                         }
1579 
1580                         xTargetLib->insertByName( *pSourceElementName, aElement );
1581                     }
1582 
1583                     // transfer the read-only flag
1584                     xTargetLibraries->setLibraryReadOnly(
1585                         sNewLibName, xSourceLibraries->isLibraryReadOnly( *pSourceLibName ) );
1586                 }
1587 
1588                 // remove the source lib
1589                 xSourceLibraries->removeLibrary( *pSourceLibName );
1590 
1591                 // tell the logger
1592                 m_rLogger.movedLibrary( m_nCurrentDocumentID, _eScriptType, *pSourceLibName, sNewLibName );
1593 
1594                 // tell the progress
1595                 _rProgress.advancePhase( pSourceLibName - pSourceLibBegin );
1596             }
1597 
1598             // clean up
1599             xSourceLibraries->storeLibraries();
1600 
1601             xTargetLibraries->storeLibraries();
1602             Reference< XStorage > xTargetRoot( xTargetLibraries->getRootLocation(), UNO_QUERY_THROW );
1603             bSuccess = lcl_commitStorage_nothrow( xTargetRoot );
1604         }
1605         catch( const Exception& )
1606         {
1607             aException = ::cppu::getCaughtException();
1608             bSuccess = false;
1609         }
1610         } while ( false );
1611 
1612         // log the error, if any
1613         if ( !bSuccess )
1614         {
1615             m_rLogger.logFailure( MigrationError(
1616                 ERR_GENERAL_MACRO_MIGRATION_FAILURE,
1617                 lcl_getSubDocumentDescription( _rDocument ),
1618                 aException
1619             ) );
1620         }
1621 
1622         return bSuccess;
1623     }
1624 
1625 	//--------------------------------------------------------------------
1626     bool MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow( const ::rtl::OUString& _rScriptType,
1627             ::rtl::OUString& _inout_rScriptCode ) const
1628     {
1629         OSL_PRECOND( _inout_rScriptCode.getLength(), "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: invalid script!" );
1630         if ( !_inout_rScriptCode.getLength() )
1631             return false;
1632 
1633         bool bSuccess = false;
1634         Any aException;
1635         try
1636         {
1637             if  (   !_rScriptType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Script" ) )
1638                 ||  !_rScriptType.getLength()
1639                 )
1640             {
1641                 OSL_ENSURE( false,
1642                     "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: no or unknown script type!" );
1643                 m_rLogger.logRecoverable( MigrationError(
1644                     ERR_UNKNOWN_SCRIPT_TYPE,
1645                     _rScriptType
1646                 ) );
1647                 return false;
1648             }
1649 
1650             // analyze the script URI
1651             Reference< XUriReferenceFactory > xUriRefFac = UriReferenceFactory::create( m_aContext.getUNOContext() );
1652             Reference< XVndSunStarScriptUrlReference > xUri( xUriRefFac->parse( _inout_rScriptCode ), UNO_QUERY_THROW );
1653 
1654             ::rtl::OUString sScriptLanguage = xUri->getParameter(
1655                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "language" ) ) );
1656             ScriptType eScriptType = eBasic;
1657             if ( !lcl_getScriptTypeFromLanguage( sScriptLanguage, eScriptType ) )
1658             {
1659                 OSL_ENSURE( false,
1660                     "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: unknown script language!" );
1661                 m_rLogger.logRecoverable( MigrationError(
1662                     ERR_UNKNOWN_SCRIPT_LANGUAGE,
1663                     sScriptLanguage
1664                 ) );
1665                 return false;
1666             }
1667 
1668             ::rtl::OUString sLocation = xUri->getParameter(
1669                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "location" ) ) );
1670             if ( !sLocation.equalsAscii( "document" ) )
1671             {
1672                 // only document libraries must be migrated, of course
1673                 return false;
1674             }
1675 
1676             ::rtl::OUString sScriptName = xUri->getName();
1677             sal_Int32 nLibModuleSeparator = sScriptName.indexOf( '.' );
1678             if ( nLibModuleSeparator < 0 )
1679             {
1680                 OSL_ENSURE( false,
1681                     "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: invalid/unknown location format!" );
1682                 m_rLogger.logRecoverable( MigrationError(
1683                     ERR_UNKNOWN_SCRIPT_NAME_FORMAT,
1684                     sScriptName
1685                 ) );
1686                 return false;
1687             }
1688 
1689             // replace the library name
1690             ::rtl::OUString sLibrary = sScriptName.copy( 0, nLibModuleSeparator );
1691             ::rtl::OUString sNewLibName = m_rLogger.getNewLibraryName(
1692                 m_nCurrentDocumentID, eScriptType, sLibrary );
1693             OSL_ENSURE( sLibrary != sNewLibName,
1694                 "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: a library which has not been migrated?" );
1695 
1696             ::rtl::OUStringBuffer aNewLocation;
1697             aNewLocation.append( sNewLibName );
1698             aNewLocation.append( sScriptName.copy( nLibModuleSeparator ) );
1699             xUri->setName( aNewLocation.makeStringAndClear() );
1700 
1701             // update the new script URL
1702             _inout_rScriptCode = xUri->getUriReference();
1703             bSuccess = true;
1704         }
1705         catch( const Exception& )
1706         {
1707             aException = ::cppu::getCaughtException();
1708             bSuccess = false;
1709         }
1710 
1711         // log the failure, if any
1712         if ( !bSuccess )
1713         {
1714             m_rLogger.logRecoverable( MigrationError(
1715                 ERR_SCRIPT_TRANSLATION_FAILURE,
1716                 _rScriptType,
1717                 _inout_rScriptCode,
1718                 aException
1719             ) );
1720         }
1721 
1722         return bSuccess;
1723     }
1724 
1725 	//--------------------------------------------------------------------
1726     bool MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow( ScriptEventDescriptor& _inout_rScriptEvent ) const
1727     {
1728         if ( _inout_rScriptEvent.ScriptType.getLength() && _inout_rScriptEvent.ScriptCode.getLength() )
1729             return impl_adjustScriptLibrary_nothrow( _inout_rScriptEvent.ScriptType, _inout_rScriptEvent.ScriptCode );
1730         return false;
1731     }
1732 
1733 	//--------------------------------------------------------------------
1734     bool MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow( Any& _inout_rScriptDescriptor ) const
1735     {
1736         ::comphelper::NamedValueCollection aScriptDesc( _inout_rScriptDescriptor );
1737 
1738         ::rtl::OUString sScriptType;
1739         ::rtl::OUString sScript;
1740         try
1741         {
1742             OSL_VERIFY( aScriptDesc.get_ensureType( "EventType", sScriptType ) );
1743             OSL_VERIFY( aScriptDesc.get_ensureType( "Script", sScript ) );
1744         }
1745         catch( const Exception& )
1746         {
1747             m_rLogger.logRecoverable( MigrationError(
1748                 ERR_INVALID_SCRIPT_DESCRIPTOR_FORMAT,
1749                 ::cppu::getCaughtException()
1750             ) );
1751         }
1752 
1753         if ( sScriptType.getLength() && sScript.getLength() )
1754             if ( !impl_adjustScriptLibrary_nothrow( sScriptType, sScript ) )
1755                 return false;
1756 
1757         aScriptDesc.put( "Script", sScript );
1758         _inout_rScriptDescriptor <<= aScriptDesc.getPropertyValues();
1759         return true;
1760     }
1761 
1762 	//--------------------------------------------------------------------
1763     bool MigrationEngine_Impl::impl_adjustDocumentEvents_nothrow( const SubDocument& _rDocument ) const
1764     {
1765         try
1766         {
1767             Reference< XEventsSupplier > xSuppEvents( _rDocument.xDocument, UNO_QUERY );
1768             if ( !xSuppEvents.is() )
1769                 // this is allowed. E.g. new-style reports currently do not support this
1770                 return true;
1771 
1772             Reference< XNameReplace > xEvents( xSuppEvents->getEvents(), UNO_SET_THROW );
1773             Sequence< ::rtl::OUString > aEventNames = xEvents->getElementNames();
1774 
1775             Any aEvent;
1776             for (   const ::rtl::OUString* eventName = aEventNames.getConstArray();
1777                     eventName != aEventNames.getConstArray() + aEventNames.getLength();
1778                     ++eventName
1779                 )
1780             {
1781                 aEvent = xEvents->getByName( *eventName );
1782                 if ( !aEvent.hasValue() )
1783                     continue;
1784 
1785                 // translate
1786                 if ( !impl_adjustScriptLibrary_nothrow( aEvent ) )
1787                     continue;
1788 
1789                 // put back
1790                 xEvents->replaceByName( *eventName, aEvent );
1791             }
1792         }
1793         catch( const Exception& )
1794         {
1795             m_rLogger.logRecoverable( MigrationError(
1796                 ERR_ADJUSTING_DOCUMENT_EVENTS_FAILED,
1797                 lcl_getSubDocumentDescription( _rDocument ),
1798                 ::cppu::getCaughtException()
1799             ) );
1800             return false;
1801         }
1802         return true;
1803     }
1804 
1805 	//--------------------------------------------------------------------
1806     void MigrationEngine_Impl::impl_adjustDialogElementEvents_throw( const Reference< XInterface >& _rxElement ) const
1807     {
1808         Reference< XScriptEventsSupplier > xEventsSupplier( _rxElement, UNO_QUERY_THROW );
1809         Reference< XNameReplace > xEvents( xEventsSupplier->getEvents(), UNO_QUERY_THROW );
1810         Sequence< ::rtl::OUString > aEventNames( xEvents->getElementNames() );
1811 
1812         const ::rtl::OUString* eventName = aEventNames.getArray();
1813         const ::rtl::OUString* eventNamesEnd = eventName + aEventNames.getLength();
1814 
1815         ScriptEventDescriptor aScriptEvent;
1816         for ( ; eventName != eventNamesEnd; ++eventName )
1817         {
1818             OSL_VERIFY( xEvents->getByName( *eventName ) >>= aScriptEvent );
1819 
1820             if ( !impl_adjustScriptLibrary_nothrow( aScriptEvent ) )
1821                 continue;
1822 
1823             xEvents->replaceByName( *eventName, makeAny( aScriptEvent ) );
1824         }
1825     }
1826 
1827 	//--------------------------------------------------------------------
1828     bool MigrationEngine_Impl::impl_adjustDialogEvents_nothrow( Any& _inout_rDialogLibraryElement,
1829         const ::rtl::OUString& _rDocName, const ::rtl::OUString& _rDialogLibName, const ::rtl::OUString& _rDialogName ) const
1830     {
1831         try
1832         {
1833             // load a dialog model from the stream describing it
1834             Reference< XInputStreamProvider > xISP( _inout_rDialogLibraryElement, UNO_QUERY_THROW );
1835             Reference< XInputStream > xInput( xISP->createInputStream(), UNO_QUERY_THROW );
1836 
1837             Reference< XNameContainer > xDialogModel( m_aContext.createComponent( "com.sun.star.awt.UnoControlDialogModel" ), UNO_QUERY_THROW );
1838             ::xmlscript::importDialogModel( xInput, xDialogModel, m_aContext.getUNOContext() );
1839 
1840             // adjust the events of the dialog
1841             impl_adjustDialogElementEvents_throw( xDialogModel );
1842 
1843             // adjust the events of the controls
1844             Sequence< ::rtl::OUString > aControlNames( xDialogModel->getElementNames() );
1845             const ::rtl::OUString* controlName = aControlNames.getConstArray();
1846             const ::rtl::OUString* controlNamesEnd = controlName + aControlNames.getLength();
1847             for ( ; controlName != controlNamesEnd; ++controlName )
1848             {
1849                 impl_adjustDialogElementEvents_throw( Reference< XInterface >( xDialogModel->getByName( *controlName ), UNO_QUERY ) );
1850             }
1851 
1852             // export dialog model
1853             xISP = ::xmlscript::exportDialogModel( xDialogModel, m_aContext.getUNOContext() );
1854             _inout_rDialogLibraryElement <<= xISP;
1855         }
1856         catch( const Exception& )
1857         {
1858             m_rLogger.logRecoverable( MigrationError(
1859                 ERR_ADJUSTING_DIALOG_EVENTS_FAILED,
1860                 _rDocName,
1861                 _rDialogLibName,
1862                 _rDialogName,
1863                 ::cppu::getCaughtException()
1864             ) );
1865             return false;
1866         }
1867         return true;
1868     }
1869 
1870 	//--------------------------------------------------------------------
1871     void MigrationEngine_Impl::impl_adjustFormComponentEvents_throw( const Reference< XIndexAccess >& _rxComponentContainer ) const
1872     {
1873         FormComponentIterator aCompIter( _rxComponentContainer );
1874         while ( aCompIter.hasMore() )
1875         {
1876             // 1. adjust the component's scripts of the current component
1877             FormComponentScripts aComponent( aCompIter.next() );
1878             Sequence< ScriptEventDescriptor > aEvents( aComponent.getEvents() );
1879 
1880             bool bChangedComponentEvents = false;
1881             for (   ScriptEventDescriptor* scriptEvent = aEvents.getArray();
1882                     scriptEvent != aEvents.getArray() + aEvents.getLength();
1883                     ++scriptEvent
1884                 )
1885             {
1886                 if ( !impl_adjustScriptLibrary_nothrow( *scriptEvent ) )
1887                     continue;
1888 
1889                 bChangedComponentEvents = true;
1890             }
1891 
1892             if ( bChangedComponentEvents )
1893                 aComponent.setEvents( aEvents );
1894 
1895             // 2. step down if the component is a container itself
1896             Reference< XIndexAccess > xContainer( aComponent.getComponent(), UNO_QUERY );
1897             if ( xContainer.is() )
1898                 impl_adjustFormComponentEvents_throw( xContainer );
1899         }
1900     }
1901 
1902 	//--------------------------------------------------------------------
1903     bool MigrationEngine_Impl::impl_adjustFormComponentEvents_nothrow( const SubDocument& _rDocument ) const
1904     {
1905         try
1906         {
1907             DrawPageIterator aPageIter( _rDocument.xDocument );
1908             while ( aPageIter.hasMore() )
1909             {
1910                 Reference< XFormsSupplier > xSuppForms( aPageIter.next(), UNO_QUERY_THROW );
1911                 Reference< XIndexAccess > xForms( xSuppForms->getForms(), UNO_QUERY_THROW );
1912                 impl_adjustFormComponentEvents_throw( xForms );
1913             }
1914         }
1915         catch( const Exception& )
1916         {
1917             m_rLogger.logRecoverable( MigrationError(
1918                 ERR_ADJUSTING_FORMCOMP_EVENTS_FAILED,
1919                 lcl_getSubDocumentDescription( _rDocument ),
1920                 ::cppu::getCaughtException()
1921             ) );
1922             return false;
1923         }
1924         return true;
1925     }
1926 
1927 	//--------------------------------------------------------------------
1928     bool MigrationEngine_Impl::impl_unprotectPasswordLibrary_throw( const Reference< XLibraryContainerPassword >& _rxPasswordManager,
1929             const ScriptType _eScriptType, const ::rtl::OUString& _rLibraryName ) const
1930     {
1931         // a human-readable description of the affected library
1932         ::rtl::OUString sLibraryDescription( String(
1933             MacroMigrationResId( STR_LIBRARY_TYPE_AND_NAME ) ) );
1934         ::comphelper::string::searchAndReplaceAsciiI( sLibraryDescription, "$type$",
1935             getScriptTypeDisplayName( _eScriptType ) );
1936         ::comphelper::string::searchAndReplaceAsciiI( sLibraryDescription, "$library$",
1937             _rLibraryName );
1938 
1939         InteractionHandler aHandler( m_aContext, m_xDocumentModel );
1940         ::rtl::OUString sPassword;
1941         while ( true )
1942         {
1943             if ( !aHandler.requestDocumentPassword( sLibraryDescription, sPassword ) )
1944                 // aborted by the user
1945                 return false;
1946 
1947             bool bSuccessVerification = _rxPasswordManager->verifyLibraryPassword( _rLibraryName, sPassword );
1948             if ( bSuccessVerification )
1949                 return true;
1950         }
1951 
1952     }
1953 
1954 	//====================================================================
1955 	//= MigrationEngine
1956 	//====================================================================
1957 	//--------------------------------------------------------------------
1958     MigrationEngine::MigrationEngine( const ::comphelper::ComponentContext& _rContext,
1959             const Reference< XOfficeDatabaseDocument >& _rxDocument, IMigrationProgress& _rProgress,
1960             MigrationLog& _rLogger )
1961         :m_pImpl( new MigrationEngine_Impl( _rContext, _rxDocument, _rProgress, _rLogger ) )
1962     {
1963     }
1964 
1965 	//--------------------------------------------------------------------
1966     MigrationEngine::~MigrationEngine()
1967     {
1968     }
1969 
1970 	//--------------------------------------------------------------------
1971     sal_Int32 MigrationEngine::getFormCount() const
1972     {
1973         return m_pImpl->getFormCount();
1974     }
1975 
1976 	//--------------------------------------------------------------------
1977     sal_Int32 MigrationEngine::getReportCount() const
1978     {
1979         return m_pImpl->getReportCount();
1980     }
1981 
1982 	//--------------------------------------------------------------------
1983     bool MigrationEngine::migrateAll()
1984     {
1985         return m_pImpl->migrateAll();
1986     }
1987 
1988 //........................................................................
1989 } // namespace dbmm
1990 //........................................................................
1991