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", 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 0 : ~PhaseGuard()
789 : {
790 0 : m_rMixer.endPhase();
791 0 : }
792 :
793 0 : void start( const PhaseID _nID, const sal_uInt32 _nPhaseRange )
794 : {
795 0 : m_rMixer.startPhase( _nID, _nPhaseRange );
796 0 : }
797 :
798 : private:
799 : ProgressMixer& m_rMixer;
800 : };
801 :
802 : // MigrationEngine_Impl - declaration
803 : class MigrationEngine_Impl
804 : {
805 : public:
806 : MigrationEngine_Impl(
807 : const Reference<XComponentContext>& _rContext,
808 : const Reference< XOfficeDatabaseDocument >& _rxDocument,
809 : IMigrationProgress& _rProgress,
810 : MigrationLog& _rLogger
811 : );
812 : ~MigrationEngine_Impl();
813 :
814 0 : inline size_t getFormCount() const { return m_nFormCount; }
815 0 : inline size_t getReportCount()const { return m_nReportCount; }
816 : bool migrateAll();
817 :
818 : private:
819 : Reference<XComponentContext> m_aContext;
820 : const Reference< XOfficeDatabaseDocument > m_xDocument;
821 : const Reference< XModel > m_xDocumentModel;
822 : IMigrationProgress& m_rProgress;
823 : MigrationLog& m_rLogger;
824 : mutable DocumentID m_nCurrentDocumentID;
825 : SubDocuments m_aSubDocs;
826 : size_t m_nFormCount;
827 : size_t m_nReportCount;
828 :
829 : private:
830 : /** collects a description of all sub documents of our database document
831 :
832 : @return
833 : <TRUE/> if and only if collecting the documents was successful
834 : */
835 : bool impl_collectSubDocuments_nothrow();
836 :
837 : /** migrates the macros/scripts of the given sub document
838 : */
839 : bool impl_handleDocument_nothrow( const SubDocument& _rDocument ) const;
840 :
841 : /** checks the structure of the 'Scripts' folder of a sub document
842 : for unknown elements
843 :
844 : @return
845 : <TRUE/> if and only if the 'Scripts' folder contains known elements only.
846 : */
847 : bool impl_checkScriptStorageStructure_nothrow( const SubDocument& _rDocument ) const;
848 :
849 : /** migrates the scripts of the given "storage-based" script type
850 : */
851 : bool impl_migrateScriptStorage_nothrow(
852 : const SubDocument& _rDocument,
853 : const ScriptType _eScriptType,
854 : ProgressMixer& _rProgress,
855 : const PhaseID _nPhaseID
856 : ) const;
857 :
858 : /** migrates the content of the given "container based" libraries (Basic/Dialogs)
859 : */
860 : bool impl_migrateContainerLibraries_nothrow(
861 : const SubDocument& _rDocument,
862 : const ScriptType _eScriptType,
863 : ProgressMixer& _rProgress,
864 : const PhaseID _nPhaseID
865 : ) const;
866 :
867 : /** adjusts the events for the given dialog/element, taking into account the new names
868 : of the moved libraries
869 : */
870 : void impl_adjustDialogElementEvents_throw(
871 : const Reference< XInterface >& _rxElement
872 : ) const;
873 :
874 : /** adjusts the events in the given dialog, and its controls, taking into account the new names
875 : of the moved libraries
876 : */
877 : bool impl_adjustDialogEvents_nothrow(
878 : Any& _inout_rDialogLibraryElement,
879 : const OUString& _rDocName,
880 : const OUString& _rDialogLibName,
881 : const OUString& _rDialogName
882 : ) const;
883 :
884 : /** adjust the document-events which refer to macros/scripts in the document, taking into
885 : account the new names of the moved libraries
886 : */
887 : bool impl_adjustDocumentEvents_nothrow(
888 : const SubDocument& _rDocument
889 : ) const;
890 :
891 : /** adjusts the script references bound to form component events
892 : */
893 : bool impl_adjustFormComponentEvents_nothrow(
894 : const SubDocument& _rDocument
895 : ) const;
896 :
897 : /** adjusts the script references for the elements of the given form component container
898 : */
899 : void impl_adjustFormComponentEvents_throw(
900 : const Reference< XIndexAccess >& _rxComponentContainer
901 : ) const;
902 :
903 : /** adjusts the library name in the given script URL, so that it reflects
904 : the new name of the library
905 :
906 : @return <TRUE/>
907 : if and only if adjustments to the script code have been made
908 : */
909 : bool impl_adjustScriptLibrary_nothrow(
910 : const OUString& _rScriptType,
911 : OUString& _inout_rScriptCode
912 : ) const;
913 :
914 : bool impl_adjustScriptLibrary_nothrow( Any& _inout_rScriptDescriptor ) const;
915 : bool impl_adjustScriptLibrary_nothrow( ScriptEventDescriptor& _inout_rScriptEvent ) const;
916 :
917 : /** asks the user for a password for the given library, and unprotects the library
918 :
919 : @return <TRUE/>
920 : if and only if the library could be successfully unprotected
921 : */
922 : bool impl_unprotectPasswordLibrary_throw(
923 : const Reference< XLibraryContainerPassword >& _rxPasswordManager,
924 : const ScriptType _eScriptType,
925 : const OUString& _rLibraryName
926 : ) const;
927 : };
928 :
929 : // MigrationEngine_Impl - implementation
930 0 : MigrationEngine_Impl::MigrationEngine_Impl( const Reference<XComponentContext>& _rContext,
931 : const Reference< XOfficeDatabaseDocument >& _rxDocument, IMigrationProgress& _rProgress, MigrationLog& _rLogger )
932 : :m_aContext( _rContext )
933 : ,m_xDocument( _rxDocument )
934 : ,m_xDocumentModel( _rxDocument, UNO_QUERY_THROW )
935 : ,m_rProgress( _rProgress )
936 : ,m_rLogger( _rLogger )
937 : ,m_nCurrentDocumentID( - 1 )
938 : ,m_aSubDocs()
939 : ,m_nFormCount( 0 )
940 0 : ,m_nReportCount( 0 )
941 : {
942 0 : OSL_VERIFY( impl_collectSubDocuments_nothrow() );
943 0 : }
944 :
945 0 : MigrationEngine_Impl::~MigrationEngine_Impl()
946 : {
947 0 : }
948 :
949 0 : bool MigrationEngine_Impl::migrateAll()
950 : {
951 0 : if ( m_aSubDocs.empty() )
952 : {
953 : OSL_FAIL( "MigrationEngine_Impl::migrateAll: no forms/reports found!" );
954 : // The whole migration wizard is not expected to be called when there are no forms/reports
955 : // with macros, not to mention when there are no forms/reports at all.
956 0 : return false;
957 : }
958 :
959 : // initialize global progress
960 0 : sal_Int32 nOverallRange( m_aSubDocs.size() );
961 : OUString sProgressSkeleton(
962 : MacroMigrationResId( STR_OVERALL_PROGRESS).toString().
963 0 : replaceFirst("$overall$", OUString::number(nOverallRange)));
964 :
965 0 : m_rProgress.start( nOverallRange );
966 :
967 0 : for ( SubDocuments::const_iterator doc = m_aSubDocs.begin();
968 0 : doc != m_aSubDocs.end();
969 : ++doc
970 : )
971 : {
972 0 : sal_Int32 nOverallProgressValue( doc - m_aSubDocs.begin() + 1 );
973 : // update overall progress text
974 : OUString sOverallProgress(
975 : sProgressSkeleton.replaceFirst("$current$",
976 0 : OUString::number(nOverallProgressValue)));
977 0 : m_rProgress.setOverallProgressText( sOverallProgress );
978 :
979 : // migrate document
980 0 : if ( !impl_handleDocument_nothrow( *doc ) )
981 0 : return false;
982 :
983 : // update overall progress vallue
984 0 : m_rProgress.setOverallProgressValue( nOverallProgressValue );
985 0 : }
986 :
987 : // commit the root storage of the database document, for all changes made so far to take effect
988 0 : if ( !lcl_commitDocumentStorage_nothrow( m_xDocumentModel, m_rLogger ) )
989 0 : return false;
990 :
991 : // save the document
992 0 : if ( !lcl_storeDocument_nothrow( m_xDocumentModel, m_rLogger ) )
993 0 : return false;
994 :
995 0 : return true;
996 : }
997 :
998 : namespace
999 : {
1000 0 : void lcl_collectHierarchicalElementNames_throw(
1001 : const Reference< XNameAccess >& _rxContainer, const OUString& _rContainerLoc,
1002 : SubDocuments& _out_rDocs, const SubDocumentType _eType, size_t& _io_counter )
1003 : {
1004 : const OUString sHierarhicalBase(
1005 0 : _rContainerLoc.isEmpty() ? OUString() :
1006 0 : OUStringBuffer( _rContainerLoc ).appendAscii( "/" ).makeStringAndClear());
1007 :
1008 0 : Sequence< OUString > aElementNames( _rxContainer->getElementNames() );
1009 0 : for ( const OUString* elementName = aElementNames.getConstArray();
1010 0 : elementName != aElementNames.getConstArray() + aElementNames.getLength();
1011 : ++elementName
1012 : )
1013 : {
1014 0 : Any aElement( _rxContainer->getByName( *elementName ) );
1015 0 : OUString sElementName( sHierarhicalBase + *elementName );
1016 :
1017 0 : Reference< XNameAccess > xSubContainer( aElement, UNO_QUERY );
1018 0 : if ( xSubContainer.is() )
1019 : {
1020 0 : lcl_collectHierarchicalElementNames_throw( xSubContainer, sElementName, _out_rDocs, _eType, _io_counter );
1021 : }
1022 : else
1023 : {
1024 0 : Reference< XCommandProcessor > xCommandProcessor( aElement, UNO_QUERY );
1025 : OSL_ENSURE( xCommandProcessor.is(), "lcl_collectHierarchicalElementNames_throw: no container, and no command processor? What *is* it, then?!" );
1026 0 : if ( xCommandProcessor.is() )
1027 : {
1028 0 : _out_rDocs.push_back( SubDocument( xCommandProcessor, sElementName, _eType, ++_io_counter ) );
1029 0 : }
1030 : }
1031 0 : }
1032 0 : }
1033 : }
1034 :
1035 0 : bool MigrationEngine_Impl::impl_collectSubDocuments_nothrow()
1036 : {
1037 : OSL_PRECOND( m_xDocument.is(), "MigrationEngine_Impl::impl_collectSubDocuments_nothrow: invalid document!" );
1038 0 : if ( !m_xDocument.is() )
1039 0 : return false;
1040 :
1041 : try
1042 : {
1043 0 : Reference< XNameAccess > xDocContainer( m_xDocument->getFormDocuments(), UNO_SET_THROW );
1044 0 : m_nFormCount = 0;
1045 0 : lcl_collectHierarchicalElementNames_throw( xDocContainer, OUString(), m_aSubDocs, eForm, m_nFormCount );
1046 :
1047 0 : xDocContainer.set( m_xDocument->getReportDocuments(), UNO_SET_THROW );
1048 0 : m_nReportCount = 0;
1049 0 : lcl_collectHierarchicalElementNames_throw( xDocContainer, OUString(), m_aSubDocs, eReport, m_nReportCount );
1050 : }
1051 0 : catch( const Exception& )
1052 : {
1053 : m_rLogger.logFailure( MigrationError(
1054 : ERR_COLLECTING_DOCUMENTS_FAILED,
1055 : ::cppu::getCaughtException()
1056 0 : ) );
1057 0 : return false;
1058 : }
1059 0 : return true;
1060 : }
1061 :
1062 0 : bool MigrationEngine_Impl::impl_handleDocument_nothrow( const SubDocument& _rDocument ) const
1063 : {
1064 : OSL_ENSURE( m_nCurrentDocumentID == -1,
1065 : "MigrationEngine_Impl::impl_handleDocument_nothrow: there already is a current document!");
1066 0 : m_nCurrentDocumentID = m_rLogger.startedDocument( _rDocument.eType, _rDocument.sHierarchicalName );
1067 :
1068 : // start the progress
1069 0 : OUString sObjectName( lcl_getSubDocumentDescription( _rDocument ) );
1070 0 : m_rProgress.startObject( sObjectName, OUString(), DEFAULT_DOC_PROGRESS_RANGE );
1071 :
1072 : // load the document
1073 0 : Reference< ProgressCapture > pStatusIndicator( new ProgressCapture( sObjectName, m_rProgress ) );
1074 0 : SubDocument aSubDocument( _rDocument );
1075 0 : OpenDocResult eResult = lcl_loadSubDocument_nothrow( aSubDocument, pStatusIndicator.get(), m_rLogger );
1076 0 : if ( eResult != eOpenedDoc )
1077 : {
1078 0 : pStatusIndicator->dispose();
1079 0 : m_rProgress.endObject();
1080 0 : m_rLogger.finishedDocument( m_nCurrentDocumentID );
1081 0 : m_nCurrentDocumentID = -1;
1082 0 : return ( eResult == eIgnoreDoc );
1083 : }
1084 :
1085 : // migrate the libraries
1086 0 : ProgressDelegator aDelegator(m_rProgress, sObjectName, MacroMigrationResId(STR_MIGRATING_LIBS).toString());
1087 0 : ProgressMixer aProgressMixer( aDelegator );
1088 0 : aProgressMixer.registerPhase( PHASE_JAVASCRIPT, 1 );
1089 0 : aProgressMixer.registerPhase( PHASE_BEANSHELL, 1 );
1090 0 : aProgressMixer.registerPhase( PHASE_PYTHON, 1 );
1091 0 : aProgressMixer.registerPhase( PHASE_JAVA, 1 );
1092 0 : aProgressMixer.registerPhase( PHASE_BASIC, 5 );
1093 : // more weight than the others, assuming that usually, there are many more Basic macros than any other scripts
1094 0 : aProgressMixer.registerPhase( PHASE_DIALOGS, 1 );
1095 :
1096 0 : bool bSuccess = impl_checkScriptStorageStructure_nothrow( aSubDocument );
1097 :
1098 : // migrate storage-based script libraries (which can be handled by mere storage operations)
1099 : bSuccess = bSuccess
1100 0 : && impl_migrateScriptStorage_nothrow( aSubDocument, eJavaScript, aProgressMixer, PHASE_JAVASCRIPT )
1101 0 : && impl_migrateScriptStorage_nothrow( aSubDocument, eBeanShell, aProgressMixer, PHASE_BEANSHELL )
1102 0 : && impl_migrateScriptStorage_nothrow( aSubDocument, ePython, aProgressMixer, PHASE_PYTHON )
1103 0 : && impl_migrateScriptStorage_nothrow( aSubDocument, eJava, aProgressMixer, PHASE_JAVA );
1104 :
1105 : // migrate Basic and dialog libraries
1106 : bSuccess = bSuccess
1107 0 : && impl_migrateContainerLibraries_nothrow( aSubDocument, eBasic, aProgressMixer, PHASE_BASIC )
1108 0 : && impl_migrateContainerLibraries_nothrow( aSubDocument, eDialog, aProgressMixer, PHASE_DIALOGS );
1109 : // order matters: First Basic scripts, then dialogs. So we can adjust references from the latter
1110 : // to the former
1111 :
1112 : // adjust the events in the document
1113 : // (note that errors are ignored here - failure to convert a script reference
1114 : // is not considered a critical error)
1115 0 : if ( bSuccess )
1116 : {
1117 0 : impl_adjustDocumentEvents_nothrow( aSubDocument );
1118 0 : impl_adjustFormComponentEvents_nothrow( aSubDocument );
1119 : }
1120 :
1121 : // clean up
1122 : // store the sub document, including removal of the (now obsolete) "Scripts" sub folder
1123 0 : if ( m_rLogger.movedAnyLibrary( m_nCurrentDocumentID ) )
1124 : {
1125 : bSuccess = bSuccess
1126 0 : && ScriptsStorage::removeFromDocument( aSubDocument.xDocument, m_rLogger )
1127 0 : && lcl_commitDocumentStorage_nothrow( aSubDocument.xDocument, m_rLogger )
1128 0 : && lcl_storeEmbeddedDocument_nothrow( aSubDocument );
1129 : }
1130 :
1131 : // unload in any case, even if we were not successful
1132 0 : bSuccess = lcl_unloadSubDocument_nothrow( aSubDocument, m_rLogger )
1133 0 : && bSuccess;
1134 :
1135 0 : pStatusIndicator->dispose();
1136 :
1137 : // end the progress, just in case the ProgressCapture didn't receive the XStatusIndicator::end event
1138 0 : m_rProgress.endObject();
1139 :
1140 0 : m_rLogger.finishedDocument( m_nCurrentDocumentID );
1141 0 : m_nCurrentDocumentID = -1;
1142 0 : return bSuccess;
1143 : }
1144 :
1145 : namespace
1146 : {
1147 0 : static OUString lcl_createTargetLibName( const SubDocument& _rDocument,
1148 : const OUString& _rSourceLibName, const Reference< XNameAccess >& _rxTargetContainer )
1149 : {
1150 : // The new library name is composed from the prefix, the base name, and the old library name.
1151 0 : const OUString sPrefix = (_rDocument.eType == eForm)?OUString("Form_"): OUString("Report_");
1152 :
1153 : OUString sBaseName( _rDocument.sHierarchicalName.copy(
1154 0 : _rDocument.sHierarchicalName.lastIndexOf( '/' ) + 1 ) );
1155 : // Normalize this name. In our current storage implementation (and script containers in a document
1156 : // are finally mapped to sub storages of the document storage), not all characters are allowed.
1157 : // The bug requesting to change this is #i95409#.
1158 : // Unfortunately, the storage implementation does not complain if you use invalid characters/names, but instead
1159 : // it silently accepts them, and produces garbage in the file (#i95408).
1160 : // So, until especially the former is fixed, we need to strip all invalid characters from the name.
1161 : // #i95865#
1162 :
1163 : // The general idea is to replace invalid characters with '_'. However, since "valid" essentially means
1164 : // ASCII only, this implies that for a lot of languages, we would simply replace everything with '_',
1165 : // which of course is not desired.
1166 : // So, we use a heuristics: If the name contains at most 3 invalid characters, and as many valid as invalid
1167 : // characters, then we use the replacement. Otherwise, we just use a unambiguous number for the sub document.
1168 0 : sal_Int32 nValid=0, nInvalid=0;
1169 0 : const sal_Unicode* pBaseName = sBaseName.getStr();
1170 0 : const sal_Int32 nBaseNameLen = sBaseName.getLength();
1171 0 : for ( sal_Int32 i=0; i<nBaseNameLen; ++i )
1172 : {
1173 0 : if ( ::comphelper::OStorageHelper::IsValidZipEntryFileName( pBaseName + i, 1, false ) )
1174 0 : ++nValid;
1175 : else
1176 0 : ++nInvalid;
1177 : }
1178 0 : if ( ( nInvalid <= 3 ) && ( nInvalid * 2 <= nValid ) )
1179 : { // not "too many" invalid => replace them
1180 0 : OUStringBuffer aReplacement;
1181 0 : aReplacement.ensureCapacity( nBaseNameLen );
1182 0 : aReplacement.append( sBaseName );
1183 0 : const sal_Unicode* pReplacement = aReplacement.getStr();
1184 0 : for ( sal_Int32 i=0; i<nBaseNameLen; ++i )
1185 : {
1186 0 : if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( pReplacement + i, 1, false ) )
1187 0 : aReplacement[i] = '_';
1188 : }
1189 0 : sBaseName = aReplacement.makeStringAndClear();
1190 :
1191 0 : OUString sTargetName( sPrefix + sBaseName + "_" + _rSourceLibName );
1192 0 : if ( !_rxTargetContainer->hasByName( sTargetName ) )
1193 0 : return sTargetName;
1194 : }
1195 :
1196 : // "too many" invalid characters, or the name composed with the base name was already used.
1197 : // (The latter is valid, since there can be multiple sub documents with the same base name,
1198 : // in different levels in the hierarchy.)
1199 : // In this case, just use the umambiguous sub document number.
1200 0 : return sPrefix + OUString::number( _rDocument.nNumber ) + "_" + _rSourceLibName;
1201 : }
1202 : }
1203 :
1204 0 : bool MigrationEngine_Impl::impl_checkScriptStorageStructure_nothrow( const SubDocument& _rDocument ) const
1205 : {
1206 : OSL_PRECOND( _rDocument.xDocument.is(), "MigrationEngine_Impl::impl_checkScriptStorageStructure_nothrow: invalid document!" );
1207 0 : if ( !_rDocument.xDocument.is() )
1208 0 : return false;
1209 :
1210 : try
1211 : {
1212 : // the root storage of the document whose scripts are to be migrated
1213 0 : ScriptsStorage aDocStorage( _rDocument.xDocument, m_rLogger );
1214 0 : if ( !aDocStorage.isValid() )
1215 : { // no scripts at all, or no scripts of the given type
1216 0 : return !m_rLogger.hadFailure();
1217 : }
1218 0 : ::std::set< OUString > aElementNames( aDocStorage.getElementNames() );
1219 :
1220 : ScriptType aKnownStorageBasedTypes[] = {
1221 : eBeanShell, eJavaScript, ePython, eJava
1222 0 : };
1223 0 : for ( size_t i=0; i<sizeof( aKnownStorageBasedTypes ) / sizeof( aKnownStorageBasedTypes[0] ); ++i )
1224 0 : aElementNames.erase( lcl_getScriptsSubStorageName( aKnownStorageBasedTypes[i] ) );
1225 :
1226 0 : if ( !aElementNames.empty() )
1227 : {
1228 : m_rLogger.logFailure( MigrationError(
1229 : ERR_UNKNOWN_SCRIPT_FOLDER,
1230 : lcl_getSubDocumentDescription( _rDocument ),
1231 0 : *aElementNames.begin()
1232 0 : ) );
1233 0 : return false;
1234 0 : }
1235 : }
1236 0 : catch( const Exception& )
1237 : {
1238 : m_rLogger.logFailure( MigrationError(
1239 : ERR_EXAMINING_SCRIPTS_FOLDER_FAILED,
1240 : lcl_getSubDocumentDescription( _rDocument ),
1241 : ::cppu::getCaughtException()
1242 0 : ) );
1243 0 : return false;
1244 : }
1245 0 : return true;
1246 : }
1247 :
1248 0 : bool MigrationEngine_Impl::impl_migrateScriptStorage_nothrow( const SubDocument& _rDocument,
1249 : const ScriptType _eScriptType, ProgressMixer& _rProgress, const PhaseID _nPhaseID ) const
1250 : {
1251 : OSL_PRECOND( _rDocument.xDocument.is(), "MigrationEngine_Impl::impl_migrateScriptStorage_nothrow: invalid document!" );
1252 0 : if ( !_rDocument.xDocument.is() )
1253 0 : return false;
1254 :
1255 0 : ScriptsStorage aDatabaseScripts( m_rLogger );
1256 : // the scripts of our complete database document - created on demand only
1257 0 : SharedStorage xTargetStorage;
1258 : // the target for moving the scripts storages - created on demand only
1259 :
1260 0 : PhaseGuard aPhase( _rProgress );
1261 0 : bool bSuccess = false;
1262 0 : Any aException;
1263 : try
1264 : {
1265 : // the root storage of the document whose scripts are to be migrated
1266 0 : ScriptsStorage aDocStorage( _rDocument.xDocument, m_rLogger );
1267 0 : if ( !aDocStorage.isValid()
1268 0 : || !aDocStorage.hasScripts( _eScriptType )
1269 : )
1270 : {
1271 : // no scripts at all, or no scripts of the given type
1272 0 : _rProgress.startPhase( _nPhaseID, 1 );
1273 0 : _rProgress.endPhase();
1274 0 : return !m_rLogger.hadFailure();
1275 : }
1276 :
1277 0 : SharedStorage xScriptsRoot( aDocStorage.getScriptsRoot( _eScriptType ) );
1278 0 : if ( !xScriptsRoot.is() )
1279 0 : throw RuntimeException("internal error");
1280 :
1281 : // loop through the script libraries
1282 0 : Sequence< OUString > aStorageElements( xScriptsRoot->getElementNames() );
1283 0 : aPhase.start( _nPhaseID, aStorageElements.getLength() );
1284 :
1285 0 : for ( const OUString* element = aStorageElements.getConstArray();
1286 0 : element != aStorageElements.getConstArray() + aStorageElements.getLength();
1287 : ++element
1288 : )
1289 : {
1290 0 : bool bIsScriptLibrary = xScriptsRoot->isStorageElement( *element );
1291 : OSL_ENSURE( bIsScriptLibrary,
1292 : "MigrationEngine_Impl::impl_migrateScriptStorage_nothrow: warning: unknown scripts storage structure!" );
1293 : // we cannot handle this. We would need to copy this stream to the respective scripts storage
1294 : // of the database document, but we cannot guarantee that the name is not used, yet, and we cannot
1295 : // simply rename the thing.
1296 0 : if ( !bIsScriptLibrary )
1297 : {
1298 : m_rLogger.logFailure( MigrationError(
1299 : ERR_UNEXPECTED_LIBSTORAGE_ELEMENT,
1300 : lcl_getSubDocumentDescription( _rDocument ),
1301 : getScriptTypeDisplayName( _eScriptType ),
1302 : *element
1303 0 : ) );
1304 0 : return false;
1305 : }
1306 :
1307 : // ensure we have access to the DBDoc's scripts storage
1308 0 : if ( !aDatabaseScripts.isValid() )
1309 : { // not needed 'til now
1310 0 : aDatabaseScripts.bind( m_xDocumentModel );
1311 0 : if ( aDatabaseScripts.isValid() )
1312 0 : xTargetStorage = aDatabaseScripts.getScriptsRoot( _eScriptType );
1313 :
1314 0 : if ( !xTargetStorage.is() )
1315 : {
1316 : m_rLogger.logFailure( MigrationError(
1317 : ERR_CREATING_DBDOC_SCRIPT_STORAGE_FAILED,
1318 : getScriptTypeDisplayName( _eScriptType )
1319 0 : ) );
1320 0 : return false;
1321 : }
1322 : }
1323 :
1324 : // move the library to the DBDoc's scripts library, under the new name
1325 0 : OUString sNewLibName( lcl_createTargetLibName( _rDocument, *element, xTargetStorage.getTyped().get() ) );
1326 0 : xScriptsRoot->moveElementTo( *element, xTargetStorage, sNewLibName );
1327 :
1328 : // log the fact that we moved the library
1329 0 : m_rLogger.movedLibrary( m_nCurrentDocumentID, _eScriptType, *element, sNewLibName );
1330 :
1331 : // progress
1332 0 : _rProgress.advancePhase( element - aStorageElements.getConstArray() );
1333 0 : }
1334 :
1335 : // commit the storages, so the changes we made persist
1336 0 : if ( !lcl_commitStorage_nothrow( xScriptsRoot )
1337 0 : || ( xTargetStorage.is() && !lcl_commitStorage_nothrow( xTargetStorage ) )
1338 : )
1339 : {
1340 : m_rLogger.logFailure( MigrationError(
1341 : ERR_COMMITTING_SCRIPT_STORAGES_FAILED,
1342 : getScriptTypeDisplayName( _eScriptType ),
1343 : lcl_getSubDocumentDescription( _rDocument )
1344 0 : ) );
1345 0 : return false;
1346 : }
1347 :
1348 : // now that the concrete scripts storage does not have any elements anymore,
1349 : // remove it
1350 0 : xScriptsRoot.reset( NULL ); // need to reset the storage to be allowed to remove it
1351 0 : aDocStorage.removeScriptTypeStorage( _eScriptType );
1352 :
1353 : // done so far
1354 0 : bSuccess = aDocStorage.commit()
1355 0 : && aDatabaseScripts.commit();
1356 : }
1357 0 : catch( const Exception& )
1358 : {
1359 0 : aException = ::cppu::getCaughtException();
1360 0 : bSuccess = false;
1361 : }
1362 :
1363 : // log the error, if any
1364 0 : if ( !bSuccess )
1365 : {
1366 : m_rLogger.logFailure( MigrationError(
1367 : ERR_GENERAL_SCRIPT_MIGRATION_FAILURE,
1368 : getScriptTypeDisplayName( _eScriptType ),
1369 : lcl_getSubDocumentDescription( _rDocument ),
1370 : aException
1371 0 : ) );
1372 : }
1373 :
1374 0 : return bSuccess;
1375 : }
1376 :
1377 0 : bool MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow( const SubDocument& _rDocument,
1378 : const ScriptType _eScriptType, ProgressMixer& _rProgress, const PhaseID _nPhaseID ) const
1379 : {
1380 : OSL_PRECOND( ( _eScriptType == eBasic ) || ( _eScriptType == eDialog ),
1381 : "MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow: illegal script type!" );
1382 :
1383 0 : bool bSuccess = false;
1384 0 : PhaseGuard aPhase( _rProgress );
1385 0 : Any aException;
1386 : do // artificial loop for flow control only
1387 : {
1388 : try
1389 : {
1390 : // access library container of the sub document
1391 0 : Reference< XEmbeddedScripts > xSubDocScripts( _rDocument.xDocument, UNO_QUERY );
1392 0 : if ( !xSubDocScripts.is() )
1393 : { // no script support in the sub document -> nothing to migrate
1394 : // (though ... this is suspicious, at least ...)
1395 0 : bSuccess = true;
1396 0 : break;
1397 : }
1398 :
1399 : Reference< XStorageBasedLibraryContainer > xSourceLibraries(
1400 0 : _eScriptType == eBasic ? xSubDocScripts->getBasicLibraries() : xSubDocScripts->getDialogLibraries(),
1401 : UNO_QUERY_THROW
1402 0 : );
1403 0 : Reference< XLibraryContainerPassword > xSourcePasswords( xSourceLibraries, UNO_QUERY );
1404 : OSL_ENSURE( xSourcePasswords.is(),
1405 : "MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow: suspicious: no password management for the source libraries!" );
1406 :
1407 0 : Sequence< OUString > aSourceLibNames( xSourceLibraries->getElementNames() );
1408 0 : aPhase.start( _nPhaseID, aSourceLibNames.getLength() );
1409 :
1410 0 : if ( !xSourceLibraries->hasElements() )
1411 : {
1412 0 : bSuccess = true;
1413 0 : break;
1414 : }
1415 :
1416 : // create library containers for the document - those will be the target for the migration
1417 0 : Reference< XStorageBasedDocument > xStorageDoc( m_xDocument, UNO_QUERY_THROW );
1418 0 : Reference< XStorageBasedLibraryContainer > xTargetLibraries;
1419 0 : if ( _eScriptType == eBasic )
1420 : {
1421 : xTargetLibraries.set( DocumentScriptLibraryContainer::create(
1422 0 : m_aContext, xStorageDoc ), UNO_QUERY_THROW );
1423 : }
1424 : else
1425 : {
1426 : xTargetLibraries.set( DocumentDialogLibraryContainer::create(
1427 0 : m_aContext, xStorageDoc ), UNO_QUERY_THROW );
1428 : }
1429 :
1430 : // copy all libs to the target, with potentially renaming them
1431 0 : const OUString* pSourceLibBegin = aSourceLibNames.getConstArray();
1432 0 : const OUString* pSourceLibEnd = pSourceLibBegin + aSourceLibNames.getLength();
1433 0 : for ( const OUString* pSourceLibName = pSourceLibBegin;
1434 : pSourceLibName != pSourceLibEnd;
1435 : ++pSourceLibName
1436 : )
1437 : {
1438 : // if the library is password-protected, ask the user to unprotect it
1439 0 : if ( xSourcePasswords.is()
1440 0 : && xSourcePasswords->isLibraryPasswordProtected( *pSourceLibName )
1441 0 : && !xSourcePasswords->isLibraryPasswordVerified( *pSourceLibName )
1442 : )
1443 : {
1444 0 : if ( !impl_unprotectPasswordLibrary_throw( xSourcePasswords, _eScriptType, *pSourceLibName ) )
1445 : {
1446 : m_rLogger.logFailure( MigrationError(
1447 : ERR_PASSWORD_VERIFICATION_FAILED,
1448 : _rDocument.sHierarchicalName,
1449 : getScriptTypeDisplayName( _eScriptType ),
1450 : *pSourceLibName
1451 0 : ) );
1452 0 : return false;
1453 : }
1454 : }
1455 :
1456 0 : OUString sNewLibName( lcl_createTargetLibName( _rDocument, *pSourceLibName, xTargetLibraries.get() ) );
1457 :
1458 0 : if ( xSourceLibraries->isLibraryLink( *pSourceLibName ) )
1459 : {
1460 : // just re-create the link in the target library
1461 0 : xTargetLibraries->createLibraryLink(
1462 : sNewLibName,
1463 0 : xSourceLibraries->getLibraryLinkURL( *pSourceLibName ),
1464 0 : xSourceLibraries->isLibraryReadOnly( *pSourceLibName )
1465 0 : );
1466 : }
1467 : else
1468 : {
1469 0 : if ( !xSourceLibraries->isLibraryLoaded( *pSourceLibName ) )
1470 0 : xSourceLibraries->loadLibrary( *pSourceLibName );
1471 :
1472 : // copy the content of this particular library
1473 0 : Reference< XNameAccess > xSourceLib( xSourceLibraries->getByName( *pSourceLibName ), UNO_QUERY_THROW );
1474 0 : Reference< XNameContainer > xTargetLib( xTargetLibraries->createLibrary( sNewLibName ), UNO_QUERY_THROW );
1475 :
1476 0 : Sequence< OUString > aLibElementNames( xSourceLib->getElementNames() );
1477 0 : for ( const OUString* pSourceElementName = aLibElementNames.getConstArray();
1478 0 : pSourceElementName != aLibElementNames.getConstArray() + aLibElementNames.getLength();
1479 : ++pSourceElementName
1480 : )
1481 : {
1482 0 : Any aElement = xSourceLib->getByName( *pSourceElementName );
1483 : OSL_ENSURE( aElement.hasValue(),
1484 : "MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow: invalid (empty) lib element!" );
1485 :
1486 : // if this is a dialog, adjust the references to scripts
1487 0 : if ( _eScriptType == eDialog )
1488 : {
1489 : impl_adjustDialogEvents_nothrow( aElement, lcl_getSubDocumentDescription( _rDocument ),
1490 0 : *pSourceLibName, *pSourceElementName );
1491 : }
1492 :
1493 0 : xTargetLib->insertByName( *pSourceElementName, aElement );
1494 0 : }
1495 :
1496 : // transfer the read-only flag
1497 0 : xTargetLibraries->setLibraryReadOnly(
1498 0 : sNewLibName, xSourceLibraries->isLibraryReadOnly( *pSourceLibName ) );
1499 : }
1500 :
1501 : // remove the source lib
1502 0 : xSourceLibraries->removeLibrary( *pSourceLibName );
1503 :
1504 : // tell the logger
1505 0 : m_rLogger.movedLibrary( m_nCurrentDocumentID, _eScriptType, *pSourceLibName, sNewLibName );
1506 :
1507 : // tell the progress
1508 0 : _rProgress.advancePhase( pSourceLibName - pSourceLibBegin );
1509 0 : }
1510 :
1511 : // clean up
1512 0 : xSourceLibraries->storeLibraries();
1513 :
1514 0 : xTargetLibraries->storeLibraries();
1515 0 : Reference< XStorage > xTargetRoot( xTargetLibraries->getRootLocation(), UNO_QUERY_THROW );
1516 0 : bSuccess = lcl_commitStorage_nothrow( xTargetRoot );
1517 : }
1518 0 : catch( const Exception& )
1519 : {
1520 0 : aException = ::cppu::getCaughtException();
1521 0 : bSuccess = false;
1522 : }
1523 : } while ( false );
1524 :
1525 : // log the error, if any
1526 0 : if ( !bSuccess )
1527 : {
1528 : m_rLogger.logFailure( MigrationError(
1529 : ERR_GENERAL_MACRO_MIGRATION_FAILURE,
1530 : lcl_getSubDocumentDescription( _rDocument ),
1531 : aException
1532 0 : ) );
1533 : }
1534 :
1535 0 : return bSuccess;
1536 : }
1537 :
1538 0 : bool MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow( const OUString& _rScriptType,
1539 : OUString& _inout_rScriptCode ) const
1540 : {
1541 : OSL_PRECOND( !_inout_rScriptCode.isEmpty(), "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: invalid script!" );
1542 0 : if ( _inout_rScriptCode.isEmpty() )
1543 0 : return false;
1544 :
1545 0 : bool bSuccess = false;
1546 0 : Any aException;
1547 : try
1548 : {
1549 0 : if ( _rScriptType != "Script" || _rScriptType.isEmpty() )
1550 : {
1551 : OSL_FAIL(
1552 : "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: no or unknown script type!" );
1553 : m_rLogger.logRecoverable( MigrationError(
1554 : ERR_UNKNOWN_SCRIPT_TYPE,
1555 : _rScriptType
1556 0 : ) );
1557 0 : return false;
1558 : }
1559 :
1560 : // analyze the script URI
1561 0 : Reference< XUriReferenceFactory > xUriRefFac = UriReferenceFactory::create( m_aContext );
1562 0 : Reference< XVndSunStarScriptUrlReference > xUri( xUriRefFac->parse( _inout_rScriptCode ), UNO_QUERY_THROW );
1563 :
1564 0 : OUString sScriptLanguage = xUri->getParameter( OUString( "language" ) );
1565 0 : ScriptType eScriptType = eBasic;
1566 0 : if ( !lcl_getScriptTypeFromLanguage( sScriptLanguage, eScriptType ) )
1567 : {
1568 : OSL_FAIL(
1569 : "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: unknown script language!" );
1570 : m_rLogger.logRecoverable( MigrationError(
1571 : ERR_UNKNOWN_SCRIPT_LANGUAGE,
1572 : sScriptLanguage
1573 0 : ) );
1574 0 : return false;
1575 : }
1576 :
1577 0 : OUString sLocation = xUri->getParameter( OUString( "location" ) );
1578 0 : if ( sLocation != "document" )
1579 : {
1580 : // only document libraries must be migrated, of course
1581 0 : return false;
1582 : }
1583 :
1584 0 : OUString sScriptName = xUri->getName();
1585 0 : sal_Int32 nLibModuleSeparator = sScriptName.indexOf( '.' );
1586 0 : if ( nLibModuleSeparator < 0 )
1587 : {
1588 : OSL_FAIL(
1589 : "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: invalid/unknown location format!" );
1590 : m_rLogger.logRecoverable( MigrationError(
1591 : ERR_UNKNOWN_SCRIPT_NAME_FORMAT,
1592 : sScriptName
1593 0 : ) );
1594 0 : return false;
1595 : }
1596 :
1597 : // replace the library name
1598 0 : OUString sLibrary = sScriptName.copy( 0, nLibModuleSeparator );
1599 : OUString sNewLibName = m_rLogger.getNewLibraryName(
1600 0 : m_nCurrentDocumentID, eScriptType, sLibrary );
1601 : OSL_ENSURE( sLibrary != sNewLibName,
1602 : "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: a library which has not been migrated?" );
1603 :
1604 0 : xUri->setName( sNewLibName + sScriptName.copy( nLibModuleSeparator ) );
1605 :
1606 : // update the new script URL
1607 0 : _inout_rScriptCode = xUri->getUriReference();
1608 0 : bSuccess = true;
1609 : }
1610 0 : catch( const Exception& )
1611 : {
1612 0 : aException = ::cppu::getCaughtException();
1613 0 : bSuccess = false;
1614 : }
1615 :
1616 : // log the failure, if any
1617 0 : if ( !bSuccess )
1618 : {
1619 : m_rLogger.logRecoverable( MigrationError(
1620 : ERR_SCRIPT_TRANSLATION_FAILURE,
1621 : _rScriptType,
1622 : _inout_rScriptCode,
1623 : aException
1624 0 : ) );
1625 : }
1626 :
1627 0 : return bSuccess;
1628 : }
1629 :
1630 0 : bool MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow( ScriptEventDescriptor& _inout_rScriptEvent ) const
1631 : {
1632 0 : if ( !(_inout_rScriptEvent.ScriptType.isEmpty() || _inout_rScriptEvent.ScriptCode.isEmpty()) )
1633 0 : return impl_adjustScriptLibrary_nothrow( _inout_rScriptEvent.ScriptType, _inout_rScriptEvent.ScriptCode );
1634 0 : return false;
1635 : }
1636 :
1637 0 : bool MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow( Any& _inout_rScriptDescriptor ) const
1638 : {
1639 0 : ::comphelper::NamedValueCollection aScriptDesc( _inout_rScriptDescriptor );
1640 :
1641 0 : OUString sScriptType;
1642 0 : OUString sScript;
1643 : try
1644 : {
1645 0 : OSL_VERIFY( aScriptDesc.get_ensureType( "EventType", sScriptType ) );
1646 0 : OSL_VERIFY( aScriptDesc.get_ensureType( "Script", sScript ) );
1647 : }
1648 0 : catch( const Exception& )
1649 : {
1650 : m_rLogger.logRecoverable( MigrationError(
1651 : ERR_INVALID_SCRIPT_DESCRIPTOR_FORMAT,
1652 : ::cppu::getCaughtException()
1653 0 : ) );
1654 : }
1655 :
1656 0 : if ( !(sScriptType.isEmpty() || sScript.isEmpty()) )
1657 0 : if ( !impl_adjustScriptLibrary_nothrow( sScriptType, sScript ) )
1658 0 : return false;
1659 :
1660 0 : aScriptDesc.put( "Script", sScript );
1661 0 : _inout_rScriptDescriptor <<= aScriptDesc.getPropertyValues();
1662 0 : return true;
1663 : }
1664 :
1665 0 : bool MigrationEngine_Impl::impl_adjustDocumentEvents_nothrow( const SubDocument& _rDocument ) const
1666 : {
1667 : try
1668 : {
1669 0 : Reference< XEventsSupplier > xSuppEvents( _rDocument.xDocument, UNO_QUERY );
1670 0 : if ( !xSuppEvents.is() )
1671 : // this is allowed. E.g. new-style reports currently do not support this
1672 0 : return true;
1673 :
1674 0 : Reference< XNameReplace > xEvents( xSuppEvents->getEvents(), UNO_SET_THROW );
1675 0 : Sequence< OUString > aEventNames = xEvents->getElementNames();
1676 :
1677 0 : Any aEvent;
1678 0 : for ( const OUString* eventName = aEventNames.getConstArray();
1679 0 : eventName != aEventNames.getConstArray() + aEventNames.getLength();
1680 : ++eventName
1681 : )
1682 : {
1683 0 : aEvent = xEvents->getByName( *eventName );
1684 0 : if ( !aEvent.hasValue() )
1685 0 : continue;
1686 :
1687 : // translate
1688 0 : if ( !impl_adjustScriptLibrary_nothrow( aEvent ) )
1689 0 : continue;
1690 :
1691 : // put back
1692 0 : xEvents->replaceByName( *eventName, aEvent );
1693 0 : }
1694 : }
1695 0 : catch( const Exception& )
1696 : {
1697 : m_rLogger.logRecoverable( MigrationError(
1698 : ERR_ADJUSTING_DOCUMENT_EVENTS_FAILED,
1699 : lcl_getSubDocumentDescription( _rDocument ),
1700 : ::cppu::getCaughtException()
1701 0 : ) );
1702 0 : return false;
1703 : }
1704 0 : return true;
1705 : }
1706 :
1707 0 : void MigrationEngine_Impl::impl_adjustDialogElementEvents_throw( const Reference< XInterface >& _rxElement ) const
1708 : {
1709 0 : Reference< XScriptEventsSupplier > xEventsSupplier( _rxElement, UNO_QUERY_THROW );
1710 0 : Reference< XNameReplace > xEvents( xEventsSupplier->getEvents(), UNO_QUERY_THROW );
1711 0 : Sequence< OUString > aEventNames( xEvents->getElementNames() );
1712 :
1713 0 : const OUString* eventName = aEventNames.getArray();
1714 0 : const OUString* eventNamesEnd = eventName + aEventNames.getLength();
1715 :
1716 0 : ScriptEventDescriptor aScriptEvent;
1717 0 : for ( ; eventName != eventNamesEnd; ++eventName )
1718 : {
1719 0 : OSL_VERIFY( xEvents->getByName( *eventName ) >>= aScriptEvent );
1720 :
1721 0 : if ( !impl_adjustScriptLibrary_nothrow( aScriptEvent ) )
1722 0 : continue;
1723 :
1724 0 : xEvents->replaceByName( *eventName, makeAny( aScriptEvent ) );
1725 0 : }
1726 0 : }
1727 :
1728 0 : bool MigrationEngine_Impl::impl_adjustDialogEvents_nothrow( Any& _inout_rDialogLibraryElement,
1729 : const OUString& _rDocName, const OUString& _rDialogLibName, const OUString& _rDialogName ) const
1730 : {
1731 : try
1732 : {
1733 : // load a dialog model from the stream describing it
1734 0 : Reference< XInputStreamProvider > xISP( _inout_rDialogLibraryElement, UNO_QUERY_THROW );
1735 0 : Reference< XInputStream > xInput( xISP->createInputStream(), UNO_QUERY_THROW );
1736 :
1737 0 : Reference< XNameContainer > xDialogModel( m_aContext->getServiceManager()->createInstanceWithContext("com.sun.star.awt.UnoControlDialogModel", m_aContext), UNO_QUERY_THROW );
1738 0 : ::xmlscript::importDialogModel( xInput, xDialogModel, m_aContext, m_xDocumentModel );
1739 :
1740 : // adjust the events of the dialog
1741 0 : impl_adjustDialogElementEvents_throw( xDialogModel );
1742 :
1743 : // adjust the events of the controls
1744 0 : Sequence< OUString > aControlNames( xDialogModel->getElementNames() );
1745 0 : const OUString* controlName = aControlNames.getConstArray();
1746 0 : const OUString* controlNamesEnd = controlName + aControlNames.getLength();
1747 0 : for ( ; controlName != controlNamesEnd; ++controlName )
1748 : {
1749 0 : impl_adjustDialogElementEvents_throw( Reference< XInterface >( xDialogModel->getByName( *controlName ), UNO_QUERY ) );
1750 : }
1751 :
1752 : // export dialog model
1753 0 : xISP = ::xmlscript::exportDialogModel( xDialogModel, m_aContext, m_xDocumentModel );
1754 0 : _inout_rDialogLibraryElement <<= xISP;
1755 : }
1756 0 : catch( const Exception& )
1757 : {
1758 : m_rLogger.logRecoverable( MigrationError(
1759 : ERR_ADJUSTING_DIALOG_EVENTS_FAILED,
1760 : _rDocName,
1761 : _rDialogLibName,
1762 : _rDialogName,
1763 : ::cppu::getCaughtException()
1764 0 : ) );
1765 0 : return false;
1766 : }
1767 0 : return true;
1768 : }
1769 :
1770 0 : void MigrationEngine_Impl::impl_adjustFormComponentEvents_throw( const Reference< XIndexAccess >& _rxComponentContainer ) const
1771 : {
1772 0 : FormComponentIterator aCompIter( _rxComponentContainer );
1773 0 : while ( aCompIter.hasMore() )
1774 : {
1775 : // 1. adjust the component's scripts of the current component
1776 0 : FormComponentScripts aComponent( aCompIter.next() );
1777 0 : Sequence< ScriptEventDescriptor > aEvents( aComponent.getEvents() );
1778 :
1779 0 : bool bChangedComponentEvents = false;
1780 0 : for ( ScriptEventDescriptor* scriptEvent = aEvents.getArray();
1781 0 : scriptEvent != aEvents.getArray() + aEvents.getLength();
1782 : ++scriptEvent
1783 : )
1784 : {
1785 0 : if ( !impl_adjustScriptLibrary_nothrow( *scriptEvent ) )
1786 0 : continue;
1787 :
1788 0 : bChangedComponentEvents = true;
1789 : }
1790 :
1791 0 : if ( bChangedComponentEvents )
1792 0 : aComponent.setEvents( aEvents );
1793 :
1794 : // 2. step down if the component is a container itself
1795 0 : Reference< XIndexAccess > xContainer( aComponent.getComponent(), UNO_QUERY );
1796 0 : if ( xContainer.is() )
1797 0 : impl_adjustFormComponentEvents_throw( xContainer );
1798 0 : }
1799 0 : }
1800 :
1801 0 : bool MigrationEngine_Impl::impl_adjustFormComponentEvents_nothrow( const SubDocument& _rDocument ) const
1802 : {
1803 : try
1804 : {
1805 0 : DrawPageIterator aPageIter( _rDocument.xDocument );
1806 0 : while ( aPageIter.hasMore() )
1807 : {
1808 0 : Reference< XFormsSupplier > xSuppForms( aPageIter.next(), UNO_QUERY_THROW );
1809 0 : Reference< XIndexAccess > xForms( xSuppForms->getForms(), UNO_QUERY_THROW );
1810 0 : impl_adjustFormComponentEvents_throw( xForms );
1811 0 : }
1812 : }
1813 0 : catch( const Exception& )
1814 : {
1815 : m_rLogger.logRecoverable( MigrationError(
1816 : ERR_ADJUSTING_FORMCOMP_EVENTS_FAILED,
1817 : lcl_getSubDocumentDescription( _rDocument ),
1818 : ::cppu::getCaughtException()
1819 0 : ) );
1820 0 : return false;
1821 : }
1822 0 : return true;
1823 : }
1824 :
1825 0 : bool MigrationEngine_Impl::impl_unprotectPasswordLibrary_throw( const Reference< XLibraryContainerPassword >& _rxPasswordManager,
1826 : const ScriptType _eScriptType, const OUString& _rLibraryName ) const
1827 : {
1828 : // a human-readable description of the affected library
1829 : OUString sLibraryDescription(
1830 : MacroMigrationResId(STR_LIBRARY_TYPE_AND_NAME).toString().
1831 : replaceFirst("$type$",
1832 : getScriptTypeDisplayName(_eScriptType)).
1833 0 : replaceFirst("$library$", _rLibraryName));
1834 : //TODO: probably broken if first replaceFirst can produce
1835 : // fresh instance of "$library$" in subject string of second
1836 : // replaceFirst
1837 :
1838 0 : InteractionHandler aHandler( m_aContext, m_xDocumentModel );
1839 0 : OUString sPassword;
1840 : while ( true )
1841 : {
1842 0 : if ( !aHandler.requestDocumentPassword( sLibraryDescription, sPassword ) )
1843 : // aborted by the user
1844 0 : return false;
1845 :
1846 0 : bool bSuccessVerification = _rxPasswordManager->verifyLibraryPassword( _rLibraryName, sPassword );
1847 0 : if ( bSuccessVerification )
1848 0 : return true;
1849 0 : }
1850 :
1851 : }
1852 :
1853 : // MigrationEngine
1854 0 : MigrationEngine::MigrationEngine( const Reference<XComponentContext>& _rContext,
1855 : const Reference< XOfficeDatabaseDocument >& _rxDocument, IMigrationProgress& _rProgress,
1856 : MigrationLog& _rLogger )
1857 0 : :m_pImpl( new MigrationEngine_Impl( _rContext, _rxDocument, _rProgress, _rLogger ) )
1858 : {
1859 0 : }
1860 :
1861 0 : MigrationEngine::~MigrationEngine()
1862 : {
1863 0 : }
1864 :
1865 0 : sal_Int32 MigrationEngine::getFormCount() const
1866 : {
1867 0 : return m_pImpl->getFormCount();
1868 : }
1869 :
1870 0 : sal_Int32 MigrationEngine::getReportCount() const
1871 : {
1872 0 : return m_pImpl->getReportCount();
1873 : }
1874 :
1875 0 : bool MigrationEngine::migrateAll()
1876 : {
1877 0 : return m_pImpl->migrateAll();
1878 : }
1879 :
1880 : } // namespace dbmm
1881 :
1882 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|