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