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