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