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