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