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