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 <map>
22 : #include <new>
23 : #include <set>
24 :
25 : #include "migration.hxx"
26 : #include "migration_impl.hxx"
27 :
28 : #include <unotools/textsearch.hxx>
29 : #include <comphelper/processfactory.hxx>
30 : #include <comphelper/sequence.hxx>
31 : #include <unotools/bootstrap.hxx>
32 : #include <rtl/bootstrap.hxx>
33 : #include <rtl/uri.hxx>
34 : #include <i18npool/lang.h>
35 : #include <tools/urlobj.hxx>
36 : #include <osl/file.hxx>
37 : #include <osl/mutex.hxx>
38 : #include <osl/security.hxx>
39 : #include <unotools/configmgr.hxx>
40 :
41 : #include <com/sun/star/configuration/Update.hpp>
42 : #include <com/sun/star/configuration/theDefaultProvider.hpp>
43 : #include <com/sun/star/lang/XInitialization.hpp>
44 : #include <com/sun/star/task/XJob.hpp>
45 : #include <com/sun/star/beans/NamedValue.hpp>
46 : #include <com/sun/star/beans/XPropertySet.hpp>
47 : #include <com/sun/star/util/XRefreshable.hpp>
48 : #include <com/sun/star/util/XChangesBatch.hpp>
49 : #include <com/sun/star/util/XStringSubstitution.hpp>
50 : #include <com/sun/star/embed/ElementModes.hpp>
51 : #include <com/sun/star/embed/FileSystemStorageFactory.hpp>
52 : #include <com/sun/star/embed/XStorage.hpp>
53 : #include <com/sun/star/ui/ModuleUIConfigurationManagerSupplier.hpp>
54 : #include <com/sun/star/frame/UICommandDescription.hpp>
55 : #include <com/sun/star/ui/XUIConfiguration.hpp>
56 : #include <com/sun/star/ui/XUIConfigurationStorage.hpp>
57 : #include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
58 :
59 : using namespace osl;
60 : using namespace std;
61 : using namespace com::sun::star::task;
62 : using namespace com::sun::star::lang;
63 : using namespace com::sun::star::beans;
64 : using namespace com::sun::star::util;
65 : using namespace com::sun::star::container;
66 : using com::sun::star::uno::Exception;
67 : using namespace com::sun::star;
68 :
69 : using ::rtl::OUString;
70 : using ::rtl::OString;
71 :
72 : namespace desktop {
73 :
74 : static const char ITEM_DESCRIPTOR_COMMANDURL[] = "CommandURL";
75 : static const char ITEM_DESCRIPTOR_CONTAINER[] = "ItemDescriptorContainer";
76 : static const char ITEM_DESCRIPTOR_LABEL[] = "Label";
77 :
78 0 : ::rtl::OUString retrieveLabelFromCommand(const ::rtl::OUString& sCommand, const ::rtl::OUString& sModuleIdentifier)
79 : {
80 0 : ::rtl::OUString sLabel;
81 :
82 0 : uno::Reference< container::XNameAccess > xUICommands;
83 : uno::Reference< container::XNameAccess > const xNameAccess(
84 : frame::UICommandDescription::create(
85 0 : ::comphelper::getProcessComponentContext()) );
86 0 : xNameAccess->getByName( sModuleIdentifier ) >>= xUICommands;
87 0 : if (xUICommands.is())
88 : {
89 0 : if ( !sCommand.isEmpty() )
90 : {
91 0 : rtl::OUString aStr;
92 0 : ::uno::Sequence< beans::PropertyValue > aPropSeq;
93 : try
94 : {
95 0 : uno::Any a( xUICommands->getByName( sCommand ));
96 0 : if ( a >>= aPropSeq )
97 : {
98 0 : for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ )
99 : {
100 0 : if ( aPropSeq[i].Name == "Label" )
101 : {
102 0 : aPropSeq[i].Value >>= aStr;
103 0 : break;
104 : }
105 : }
106 : }
107 :
108 0 : sLabel = aStr;
109 : }
110 0 : catch (const container::NoSuchElementException&)
111 : {
112 0 : sLabel = sCommand;
113 0 : sal_Int32 nIndex = sLabel.indexOf(':');
114 0 : if (nIndex>=0 && nIndex <= sLabel.getLength()-1)
115 0 : sLabel = sLabel.copy(nIndex+1);
116 0 : }
117 :
118 : }
119 : }
120 :
121 0 : return sLabel;
122 : }
123 :
124 0 : ::rtl::OUString mapModuleShortNameToIdentifier(const ::rtl::OUString& sShortName)
125 : {
126 0 : ::rtl::OUString sIdentifier;
127 :
128 0 : if ( sShortName == "StartModule" )
129 0 : sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.StartModule"));
130 :
131 0 : else if ( sShortName == "swriter" )
132 0 : sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextDocument"));
133 :
134 0 : else if ( sShortName == "scalc" )
135 0 : sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.SpreadsheetDocument"));
136 :
137 0 : else if ( sShortName == "sdraw" )
138 0 : sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.DrawingDocument"));
139 :
140 0 : else if ( sShortName == "simpress" )
141 0 : sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.PresentationDocument"));
142 :
143 0 : else if ( sShortName == "smath" )
144 0 : sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.formula.FormulaProperties"));
145 :
146 0 : else if ( sShortName == "schart" )
147 0 : sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.chart2.ChartDocument"));
148 :
149 0 : else if ( sShortName == "BasicIDE" )
150 0 : sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.BasicIDE"));
151 :
152 0 : else if ( sShortName == "dbapp" )
153 0 : sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.OfficeDatabaseDocument"));
154 :
155 0 : else if ( sShortName == "sglobal" )
156 0 : sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.GlobalDocument"));
157 :
158 0 : else if ( sShortName == "sweb" )
159 0 : sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.WebDocument"));
160 :
161 0 : else if ( sShortName == "swxform" )
162 0 : sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xforms.XMLFormDocument"));
163 :
164 0 : else if ( sShortName == "sbibliography" )
165 0 : sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Bibliography"));
166 :
167 0 : return sIdentifier;
168 : }
169 :
170 0 : bool MigrationImpl::alreadyMigrated()
171 : {
172 0 : rtl::OUString MIGRATION_STAMP_NAME(RTL_CONSTASCII_USTRINGPARAM("/MIGRATED"));
173 0 : rtl::OUString aStr = m_aInfo.userdata + MIGRATION_STAMP_NAME;
174 0 : File aFile(aStr);
175 : // create migration stamp, and/or check its existence
176 0 : bool bRet = aFile.open (osl_File_OpenFlag_Write | osl_File_OpenFlag_Create | osl_File_OpenFlag_NoLock) == FileBase::E_EXIST;
177 : OSL_TRACE( "File '%s' exists? %d\n",
178 : rtl::OUStringToOString(aStr, RTL_TEXTENCODING_ASCII_US).getStr(),
179 : bRet );
180 0 : return bRet;
181 : }
182 :
183 0 : bool MigrationImpl::initializeMigration()
184 : {
185 0 : bool bRet = false;
186 :
187 0 : if (!checkMigrationCompleted()) {
188 0 : readAvailableMigrations(m_vMigrationsAvailable);
189 0 : sal_Int32 nIndex = findPreferedMigrationProcess(m_vMigrationsAvailable);
190 : // m_aInfo is now set to the preferred migration source
191 0 : if ( nIndex >= 0 ) {
192 0 : if (alreadyMigrated())
193 0 : return false;
194 0 : m_vrMigrations = readMigrationSteps(m_vMigrationsAvailable[nIndex].name);
195 : }
196 :
197 0 : bRet = !m_aInfo.userdata.isEmpty();
198 : }
199 :
200 : OSL_TRACE( "Migration %s", bRet ? "needed" : "not required" );
201 :
202 0 : return bRet;
203 : }
204 :
205 0 : void Migration::migrateSettingsIfNecessary()
206 : {
207 0 : MigrationImpl aImpl( comphelper::getProcessServiceFactory() );
208 :
209 0 : if (! aImpl.initializeMigration() )
210 0 : return;
211 :
212 0 : sal_Bool bResult = sal_False;
213 : try
214 : {
215 0 : bResult = aImpl.doMigration();
216 : }
217 0 : catch (const Exception& e)
218 : {
219 0 : OString aMsg("doMigration() exception: ");
220 0 : aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
221 0 : OSL_FAIL(aMsg.getStr());
222 : }
223 : OSL_ENSURE(bResult, "Migration has not been successfull");
224 0 : (void)bResult;
225 : }
226 :
227 0 : MigrationImpl::MigrationImpl(const uno::Reference< XMultiServiceFactory >& xFactory)
228 0 : : m_vrVersions(new strings_v)
229 0 : , m_xFactory(xFactory)
230 : {
231 0 : }
232 :
233 0 : MigrationImpl::~MigrationImpl()
234 : {
235 0 : }
236 :
237 : // The main entry point for migrating settings
238 0 : sal_Bool MigrationImpl::doMigration()
239 : {
240 : // compile file list for migration
241 0 : m_vrFileList = compileFileList();
242 :
243 0 : sal_Bool result = sal_False;
244 : try
245 : {
246 0 : NewVersionUIInfo aNewVersionUIInfo;
247 0 : ::std::vector< MigrationModuleInfo > vModulesInfo = dectectUIChangesForAllModules();
248 0 : aNewVersionUIInfo.init(vModulesInfo);
249 :
250 0 : copyFiles();
251 :
252 0 : const ::rtl::OUString sMenubarResourceURL(RTL_CONSTASCII_USTRINGPARAM("private:resource/menubar/menubar"));
253 0 : const ::rtl::OUString sToolbarResourcePre(RTL_CONSTASCII_USTRINGPARAM("private:resource/toolbar/"));
254 0 : for (sal_uInt32 i=0; i<vModulesInfo.size(); ++i)
255 : {
256 0 : ::rtl::OUString sModuleIdentifier = mapModuleShortNameToIdentifier(vModulesInfo[i].sModuleShortName);
257 0 : if (sModuleIdentifier.isEmpty())
258 0 : continue;
259 :
260 0 : uno::Sequence< uno::Any > lArgs(2);
261 0 : ::rtl::OUString aOldCfgDataPath = m_aInfo.userdata + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/user/config/soffice.cfg/modules/"));
262 0 : lArgs[0] <<= aOldCfgDataPath + vModulesInfo[i].sModuleShortName;
263 0 : lArgs[1] <<= embed::ElementModes::READ;
264 :
265 : uno::Reference< lang::XSingleServiceFactory > xStorageFactory(
266 0 : embed::FileSystemStorageFactory::create(comphelper::getComponentContext(m_xFactory)));
267 0 : uno::Reference< embed::XStorage > xModules(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY);
268 0 : uno::Reference< ui::XUIConfigurationManager > xOldCfgManager( m_xFactory->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.UIConfigurationManager"))), uno::UNO_QUERY );
269 0 : uno::Reference< ui::XUIConfigurationStorage > xOldCfgStorage( xOldCfgManager, uno::UNO_QUERY );
270 0 : uno::Reference< ui::XUIConfigurationPersistence > xOldCfgPersistence( xOldCfgManager, uno::UNO_QUERY );
271 :
272 0 : if ( xOldCfgStorage.is() && xOldCfgPersistence.is() && xModules.is() )
273 : {
274 0 : xOldCfgStorage->setStorage( xModules );
275 0 : xOldCfgPersistence->reload();
276 : }
277 :
278 0 : uno::Reference< ui::XUIConfigurationManager > xCfgManager = aNewVersionUIInfo.getConfigManager(vModulesInfo[i].sModuleShortName);
279 :
280 0 : if (vModulesInfo[i].bHasMenubar)
281 : {
282 0 : uno::Reference< container::XIndexContainer > xOldVersionMenuSettings = uno::Reference< container::XIndexContainer >(xOldCfgManager->getSettings(sMenubarResourceURL, sal_True), uno::UNO_QUERY);
283 0 : uno::Reference< container::XIndexContainer > xNewVersionMenuSettings = aNewVersionUIInfo.getNewMenubarSettings(vModulesInfo[i].sModuleShortName);
284 0 : ::rtl::OUString sParent;
285 0 : compareOldAndNewConfig(sParent, xOldVersionMenuSettings, xNewVersionMenuSettings, sMenubarResourceURL);
286 0 : mergeOldToNewVersion(xCfgManager, xNewVersionMenuSettings, sModuleIdentifier, sMenubarResourceURL);
287 : }
288 :
289 0 : sal_Int32 nToolbars = vModulesInfo[i].m_vToolbars.size();
290 0 : if (nToolbars >0)
291 : {
292 0 : for (sal_Int32 j=0; j<nToolbars; ++j)
293 : {
294 0 : ::rtl::OUString sToolbarName = vModulesInfo[i].m_vToolbars[j];
295 0 : ::rtl::OUString sToolbarResourceURL = sToolbarResourcePre + sToolbarName;
296 :
297 0 : uno::Reference< container::XIndexContainer > xOldVersionToolbarSettings = uno::Reference< container::XIndexContainer >(xOldCfgManager->getSettings(sToolbarResourceURL, sal_True), uno::UNO_QUERY);
298 0 : uno::Reference< container::XIndexContainer > xNewVersionToolbarSettings = aNewVersionUIInfo.getNewToolbarSettings(vModulesInfo[i].sModuleShortName, sToolbarName);
299 0 : ::rtl::OUString sParent;
300 0 : compareOldAndNewConfig(sParent, xOldVersionToolbarSettings, xNewVersionToolbarSettings, sToolbarResourceURL);
301 0 : mergeOldToNewVersion(xCfgManager, xNewVersionToolbarSettings, sModuleIdentifier, sToolbarResourceURL);
302 0 : }
303 : }
304 :
305 0 : m_aOldVersionItemsHashMap.clear();
306 0 : m_aNewVersionItemsHashMap.clear();
307 0 : }
308 :
309 : // execute the migration items from Setup.xcu
310 0 : copyConfig();
311 :
312 : // execute custom migration services from Setup.xcu
313 : // and refresh the cache
314 0 : runServices();
315 0 : refresh();
316 :
317 0 : result = sal_True;
318 : }
319 0 : catch (...)
320 : {
321 0 : OString aMsg("An unexpected exception was thrown during migration");
322 0 : aMsg += "\nOldVersion: " + OUStringToOString(m_aInfo.productname, RTL_TEXTENCODING_ASCII_US);
323 0 : aMsg += "\nDataPath : " + OUStringToOString(m_aInfo.userdata, RTL_TEXTENCODING_ASCII_US);
324 0 : OSL_FAIL(aMsg.getStr());
325 : }
326 :
327 : // prevent running the migration multiple times
328 0 : setMigrationCompleted();
329 0 : return result;
330 : }
331 :
332 0 : void MigrationImpl::refresh()
333 : {
334 : uno::Reference< XRefreshable >(
335 : configuration::theDefaultProvider::get(
336 : comphelper::getComponentContext(m_xFactory)),
337 0 : uno::UNO_QUERY_THROW)->refresh();
338 0 : }
339 :
340 0 : void MigrationImpl::setMigrationCompleted()
341 : {
342 : try
343 : {
344 0 : uno::Reference< XPropertySet > aPropertySet(getConfigAccess("org.openoffice.Setup/Office", true), uno::UNO_QUERY_THROW);
345 0 : aPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("MigrationCompleted")), uno::makeAny(sal_True));
346 0 : uno::Reference< XChangesBatch >(aPropertySet, uno::UNO_QUERY_THROW)->commitChanges();
347 : }
348 0 : catch (...)
349 : {
350 : // fail silently
351 : }
352 0 : }
353 :
354 0 : bool MigrationImpl::checkMigrationCompleted()
355 : {
356 0 : sal_Bool bMigrationCompleted = sal_False;
357 : try {
358 : uno::Reference< XPropertySet > aPropertySet(
359 0 : getConfigAccess("org.openoffice.Setup/Office"), uno::UNO_QUERY_THROW);
360 0 : aPropertySet->getPropertyValue(
361 0 : OUString(RTL_CONSTASCII_USTRINGPARAM("MigrationCompleted"))) >>= bMigrationCompleted;
362 :
363 0 : if( !bMigrationCompleted && getenv("SAL_DISABLE_USERMIGRATION" ) )
364 : {
365 : // migration prevented - fake it's success
366 0 : setMigrationCompleted();
367 0 : bMigrationCompleted = sal_True;
368 0 : }
369 : }
370 0 : catch (const Exception&)
371 : {
372 : // just return false...
373 : }
374 : OSL_TRACE( "Migration %s", bMigrationCompleted ? "already completed" : "not done" );
375 :
376 0 : return bMigrationCompleted;
377 : }
378 :
379 0 : static void insertSorted(migrations_available& rAvailableMigrations, supported_migration& aSupportedMigration)
380 : {
381 0 : bool bInserted( false );
382 0 : migrations_available::iterator pIter = rAvailableMigrations.begin();
383 0 : while ( !bInserted && pIter != rAvailableMigrations.end())
384 : {
385 0 : if ( pIter->nPriority < aSupportedMigration.nPriority )
386 : {
387 0 : rAvailableMigrations.insert(pIter, aSupportedMigration );
388 0 : bInserted = true;
389 0 : break; // i111193: insert invalidates iterator!
390 : }
391 0 : ++pIter;
392 : }
393 0 : if ( !bInserted )
394 0 : rAvailableMigrations.push_back( aSupportedMigration );
395 0 : }
396 :
397 0 : bool MigrationImpl::readAvailableMigrations(migrations_available& rAvailableMigrations)
398 : {
399 : // get supported version names
400 0 : uno::Reference< XNameAccess > aMigrationAccess(getConfigAccess("org.openoffice.Setup/Migration/SupportedVersions"), uno::UNO_QUERY_THROW);
401 0 : uno::Sequence< OUString > seqSupportedVersions = aMigrationAccess->getElementNames();
402 :
403 0 : const OUString aVersionIdentifiers( RTL_CONSTASCII_USTRINGPARAM( "VersionIdentifiers" ));
404 0 : const OUString aPriorityIdentifier( RTL_CONSTASCII_USTRINGPARAM( "Priority" ));
405 :
406 0 : for (sal_Int32 i=0; i<seqSupportedVersions.getLength(); i++)
407 : {
408 0 : sal_Int32 nPriority( 0 );
409 0 : uno::Sequence< OUString > seqVersions;
410 0 : uno::Reference< XNameAccess > xMigrationData( aMigrationAccess->getByName(seqSupportedVersions[i]), uno::UNO_QUERY_THROW );
411 0 : xMigrationData->getByName( aVersionIdentifiers ) >>= seqVersions;
412 0 : xMigrationData->getByName( aPriorityIdentifier ) >>= nPriority;
413 :
414 0 : supported_migration aSupportedMigration;
415 0 : aSupportedMigration.name = seqSupportedVersions[i];
416 0 : aSupportedMigration.nPriority = nPriority;
417 0 : for (sal_Int32 j=0; j<seqVersions.getLength(); j++)
418 0 : aSupportedMigration.supported_versions.push_back(seqVersions[j].trim());
419 0 : insertSorted( rAvailableMigrations, aSupportedMigration );
420 : OSL_TRACE( " available migration '%s'\n",
421 : rtl::OUStringToOString( aSupportedMigration.name, RTL_TEXTENCODING_ASCII_US ).getStr() );
422 0 : }
423 :
424 0 : return true;
425 : }
426 :
427 0 : migrations_vr MigrationImpl::readMigrationSteps(const ::rtl::OUString& rMigrationName)
428 : {
429 : // get migration access
430 0 : uno::Reference< XNameAccess > aMigrationAccess(getConfigAccess("org.openoffice.Setup/Migration/SupportedVersions"), uno::UNO_QUERY_THROW);
431 0 : uno::Reference< XNameAccess > xMigrationData( aMigrationAccess->getByName(rMigrationName), uno::UNO_QUERY_THROW );
432 :
433 : // get migration description from from org.openoffice.Setup/Migration
434 : // and build vector of migration steps
435 0 : OUString aMigrationSteps( RTL_CONSTASCII_USTRINGPARAM( "MigrationSteps" ));
436 0 : uno::Reference< XNameAccess > theNameAccess(xMigrationData->getByName(aMigrationSteps), uno::UNO_QUERY_THROW);
437 0 : uno::Sequence< OUString > seqMigrations = theNameAccess->getElementNames();
438 0 : uno::Reference< XNameAccess > tmpAccess;
439 0 : uno::Reference< XNameAccess > tmpAccess2;
440 0 : uno::Sequence< OUString > tmpSeq;
441 0 : migrations_vr vrMigrations(new migrations_v);
442 0 : for (sal_Int32 i = 0; i < seqMigrations.getLength(); i++)
443 : {
444 : // get current migration step
445 0 : theNameAccess->getByName(seqMigrations[i]) >>= tmpAccess;
446 0 : migration_step tmpStep;
447 0 : tmpStep.name = seqMigrations[i];
448 :
449 : // read included files from current step description
450 0 : ::rtl::OUString aSeqEntry;
451 0 : if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("IncludedFiles"))) >>= tmpSeq)
452 : {
453 0 : for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
454 : {
455 0 : aSeqEntry = tmpSeq[j];
456 0 : tmpStep.includeFiles.push_back(aSeqEntry);
457 : }
458 : }
459 :
460 : // exluded files...
461 0 : if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("ExcludedFiles"))) >>= tmpSeq)
462 : {
463 0 : for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
464 0 : tmpStep.excludeFiles.push_back(tmpSeq[j]);
465 : }
466 :
467 : // included nodes...
468 0 : if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("IncludedNodes"))) >>= tmpSeq)
469 : {
470 0 : for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
471 0 : tmpStep.includeConfig.push_back(tmpSeq[j]);
472 : }
473 :
474 : // excluded nodes...
475 0 : if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("ExcludedNodes"))) >>= tmpSeq)
476 : {
477 0 : for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
478 0 : tmpStep.excludeConfig.push_back(tmpSeq[j]);
479 : }
480 :
481 : // included extensions...
482 0 : if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("IncludedExtensions"))) >>= tmpSeq)
483 : {
484 0 : for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
485 0 : tmpStep.includeExtensions.push_back(tmpSeq[j]);
486 : }
487 :
488 : // excluded extensions...
489 0 : if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("ExcludedExtensions"))) >>= tmpSeq)
490 : {
491 0 : for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
492 : {
493 0 : aSeqEntry = tmpSeq[j];
494 0 : tmpStep.excludeExtensions.push_back(aSeqEntry);
495 : }
496 : }
497 :
498 : // generic service
499 0 : tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("MigrationService"))) >>= tmpStep.service;
500 :
501 0 : vrMigrations->push_back(tmpStep);
502 0 : }
503 0 : return vrMigrations;
504 : }
505 :
506 0 : static FileBase::RC _checkAndCreateDirectory(INetURLObject& dirURL)
507 : {
508 0 : FileBase::RC result = Directory::create(dirURL.GetMainURL(INetURLObject::DECODE_TO_IURI));
509 0 : if (result == FileBase::E_NOENT)
510 : {
511 0 : INetURLObject baseURL(dirURL);
512 0 : baseURL.removeSegment();
513 0 : _checkAndCreateDirectory(baseURL);
514 0 : return Directory::create(dirURL.GetMainURL(INetURLObject::DECODE_TO_IURI));
515 : } else
516 0 : return result;
517 : }
518 :
519 : static const char XDG_CONFIG_PART[] = "/.config/";
520 :
521 : #if defined UNX && ! defined MACOSX
522 0 : OUString MigrationImpl::preXDGConfigDir(const OUString& rConfigDir)
523 : {
524 0 : OUString aPreXDGConfigPath;
525 0 : const char* pXDGCfgHome = getenv("XDG_CONFIG_HOME");
526 :
527 : // cater for XDG_CONFIG_HOME change
528 : // If XDG_CONFIG_HOME is set then we;
529 : // assume the user knows what they are doing ( room for improvement here, we could
530 : // of course search the default config dir etc. also - but this is more complex,
531 : // we would need to weigh results from the current config dir against matches in
532 : // the 'old' config dir etc. ) - currently we just use the returned config dir.
533 : // If XDG_CONFIG_HOME is NOT set;
534 : // assume then we should now using the default $HOME/,config config location for
535 : // our user profiles, however *all* previous libreoffice and openoffice.org
536 : // configurations will be in the 'old' config directory and that's where we need
537 : // to search - we convert the returned config dir to the 'old' dir
538 0 : if ( !pXDGCfgHome && rConfigDir.endsWithAsciiL( XDG_CONFIG_PART, sizeof( XDG_CONFIG_PART ) - 1 ) )
539 : // remove trailing '.config/' but leave the terminating '/'
540 0 : aPreXDGConfigPath = rConfigDir.copy( 0, rConfigDir.getLength() - sizeof( XDG_CONFIG_PART ) + 2 );
541 : else
542 0 : aPreXDGConfigPath = rConfigDir;
543 :
544 : // the application-specific config dir is not longer prefixed by '.' because it is hidden under ".config"
545 : // we have to add the '.' for the pre-XDG directory names
546 0 : aPreXDGConfigPath += ".";
547 :
548 0 : return aPreXDGConfigPath;
549 : }
550 : #endif
551 :
552 0 : void MigrationImpl::setInstallInfoIfExist(
553 : install_info& aInfo,
554 : const ::rtl::OUString& rConfigDir,
555 : const ::rtl::OUString& rVersion)
556 : {
557 0 : rtl::OUString url(INetURLObject(rConfigDir).GetMainURL(INetURLObject::NO_DECODE));
558 0 : osl::DirectoryItem item;
559 0 : osl::FileStatus stat(osl_FileStatus_Mask_Type);
560 :
561 0 : if (osl::DirectoryItem::get(url, item) == osl::FileBase::E_None
562 0 : && item.getFileStatus(stat) == osl::FileBase::E_None
563 0 : && stat.getFileType() == osl::FileStatus::Directory)
564 : {
565 0 : aInfo.userdata = url;
566 0 : aInfo.productname = rVersion;
567 0 : }
568 0 : }
569 :
570 0 : install_info MigrationImpl::findInstallation(const strings_v& rVersions)
571 : {
572 :
573 0 : OUString aTopConfigDir;
574 0 : osl::Security().getConfigDir( aTopConfigDir );
575 0 : if ( !aTopConfigDir.isEmpty() && aTopConfigDir[ aTopConfigDir.getLength()-1 ] != '/' )
576 0 : aTopConfigDir += "/";
577 :
578 : #if defined UNX && ! defined MACOSX
579 0 : OUString aPreXDGTopConfigDir = preXDGConfigDir(aTopConfigDir);
580 : #endif
581 :
582 0 : install_info aInfo;
583 0 : strings_v::const_iterator i_ver = rVersions.begin();
584 0 : while (i_ver != rVersions.end())
585 : {
586 0 : ::rtl::OUString aVersion, aProfileName;
587 0 : sal_Int32 nSeparatorIndex = (*i_ver).indexOf('=');
588 0 : if ( nSeparatorIndex != -1 )
589 : {
590 0 : aVersion = (*i_ver).copy( 0, nSeparatorIndex );
591 0 : aProfileName = (*i_ver).copy( nSeparatorIndex+1 );
592 : }
593 :
594 0 : if ( !aVersion.isEmpty() && !aProfileName.isEmpty() &&
595 0 : ( aInfo.userdata.isEmpty() ||
596 : aProfileName.equalsIgnoreAsciiCase(
597 0 : utl::ConfigManager::getProductName() ) ) )
598 : {
599 0 : setInstallInfoIfExist(aInfo, aTopConfigDir + aProfileName, aVersion);
600 : #if defined UNX && ! defined MACOSX
601 : //try preXDG path if the new one does not exist
602 0 : if ( aInfo.userdata.isEmpty())
603 0 : setInstallInfoIfExist(aInfo, aPreXDGTopConfigDir + aProfileName, aVersion);
604 : #endif
605 : }
606 0 : ++i_ver;
607 0 : }
608 :
609 0 : return aInfo;
610 : }
611 :
612 0 : sal_Int32 MigrationImpl::findPreferedMigrationProcess(const migrations_available& rAvailableMigrations)
613 : {
614 0 : sal_Int32 nIndex( -1 );
615 0 : sal_Int32 i( 0 );
616 :
617 0 : migrations_available::const_iterator rIter = rAvailableMigrations.begin();
618 0 : while ( rIter != rAvailableMigrations.end() )
619 : {
620 0 : install_info aInstallInfo = findInstallation(rIter->supported_versions);
621 0 : if (!aInstallInfo.productname.isEmpty() )
622 : {
623 0 : m_aInfo = aInstallInfo;
624 0 : nIndex = i;
625 : break;
626 : }
627 0 : ++i;
628 0 : ++rIter;
629 0 : }
630 :
631 : OSL_TRACE( " preferred migration is from product '%s'\n",
632 : rtl::OUStringToOString( m_aInfo.productname, RTL_TEXTENCODING_ASCII_US ).getStr() );
633 : OSL_TRACE( " and settings directory '%s'\n",
634 : rtl::OUStringToOString( m_aInfo.userdata, RTL_TEXTENCODING_ASCII_US ).getStr() );
635 :
636 0 : return nIndex;
637 : }
638 :
639 0 : strings_vr MigrationImpl::applyPatterns(const strings_v& vSet, const strings_v& vPatterns) const
640 : {
641 : using namespace utl;
642 0 : strings_vr vrResult(new strings_v);
643 0 : strings_v::const_iterator i_set;
644 0 : strings_v::const_iterator i_pat = vPatterns.begin();
645 0 : while (i_pat != vPatterns.end())
646 : {
647 : // find matches for this pattern in input set
648 : // and copy them to the result
649 0 : SearchParam param(*i_pat, SearchParam::SRCH_REGEXP);
650 0 : TextSearch ts(param, LANGUAGE_DONTKNOW);
651 0 : i_set = vSet.begin();
652 0 : xub_StrLen start = 0;
653 0 : xub_StrLen end = 0;
654 0 : while (i_set != vSet.end())
655 : {
656 0 : end = (xub_StrLen)(i_set->getLength());
657 0 : if (ts.SearchFrwrd(*i_set, &start, &end))
658 0 : vrResult->push_back(*i_set);
659 0 : ++i_set;
660 : }
661 0 : ++i_pat;
662 0 : }
663 0 : return vrResult;
664 : }
665 :
666 0 : strings_vr MigrationImpl::getAllFiles(const OUString& baseURL) const
667 : {
668 : using namespace osl;
669 0 : strings_vr vrResult(new strings_v);
670 :
671 : // get sub dirs
672 0 : Directory dir(baseURL);
673 0 : if (dir.open() == FileBase::E_None)
674 : {
675 0 : strings_v vSubDirs;
676 0 : strings_vr vrSubResult;
677 :
678 : // work through directory contents...
679 0 : DirectoryItem item;
680 0 : FileStatus fs(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL);
681 0 : while (dir.getNextItem(item) == FileBase::E_None)
682 : {
683 0 : if (item.getFileStatus(fs) == FileBase::E_None)
684 : {
685 0 : if (fs.getFileType() == FileStatus::Directory)
686 0 : vSubDirs.push_back(fs.getFileURL());
687 : else
688 0 : vrResult->push_back(fs.getFileURL());
689 : }
690 : }
691 :
692 : // recurse subfolders
693 0 : strings_v::const_iterator i = vSubDirs.begin();
694 0 : while (i != vSubDirs.end())
695 : {
696 0 : vrSubResult = getAllFiles(*i);
697 0 : vrResult->insert(vrResult->end(), vrSubResult->begin(), vrSubResult->end());
698 0 : ++i;
699 0 : }
700 : }
701 0 : return vrResult;
702 : }
703 :
704 0 : strings_vr MigrationImpl::compileFileList()
705 : {
706 :
707 0 : strings_vr vrResult(new strings_v);
708 0 : strings_vr vrInclude;
709 0 : strings_vr vrExclude;
710 :
711 : // get a list of all files:
712 0 : strings_vr vrFiles = getAllFiles(m_aInfo.userdata);
713 :
714 : // get a file list result for each migration step
715 0 : migrations_v::const_iterator i_migr = m_vrMigrations->begin();
716 0 : while (i_migr != m_vrMigrations->end())
717 : {
718 0 : vrInclude = applyPatterns(*vrFiles, i_migr->includeFiles);
719 0 : vrExclude = applyPatterns(*vrFiles, i_migr->excludeFiles);
720 0 : subtract(*vrInclude, *vrExclude);
721 0 : vrResult->insert(vrResult->end(), vrInclude->begin(), vrInclude->end());
722 0 : ++i_migr;
723 : }
724 0 : return vrResult;
725 : }
726 :
727 : namespace {
728 :
729 0 : struct componentParts {
730 : std::set< rtl::OUString > includedPaths;
731 : std::set< rtl::OUString > excludedPaths;
732 : };
733 :
734 : typedef std::map< rtl::OUString, componentParts > Components;
735 :
736 0 : bool getComponent(rtl::OUString const & path, rtl::OUString * component) {
737 : OSL_ASSERT(component != 0);
738 0 : if (path.isEmpty() || path[0] != '/') {
739 : OSL_TRACE(
740 : ("configuration migration in/exclude path %s ignored (does not"
741 : " start with slash)"),
742 : rtl::OUStringToOString(path, RTL_TEXTENCODING_UTF8).getStr());
743 0 : return false;
744 : }
745 0 : sal_Int32 i = path.indexOf('/', 1);
746 0 : *component = i < 0 ? path.copy(1) : path.copy(1, i - 1);
747 0 : return true;
748 : }
749 :
750 0 : uno::Sequence< rtl::OUString > setToSeq(std::set< rtl::OUString > const & set) {
751 0 : std::set< rtl::OUString >::size_type n = set.size();
752 0 : if (n > SAL_MAX_INT32) {
753 0 : throw std::bad_alloc();
754 : }
755 0 : uno::Sequence< rtl::OUString > seq(static_cast< sal_Int32 >(n));
756 0 : sal_Int32 i = 0;
757 0 : for (std::set< rtl::OUString >::const_iterator j(set.begin());
758 0 : j != set.end(); ++j)
759 : {
760 0 : seq[i++] = *j;
761 : }
762 0 : return seq;
763 : }
764 :
765 : }
766 :
767 0 : void MigrationImpl::copyConfig() {
768 0 : Components comps;
769 0 : for (migrations_v::const_iterator i(m_vrMigrations->begin());
770 0 : i != m_vrMigrations->end(); ++i)
771 : {
772 0 : for (strings_v::const_iterator j(i->includeConfig.begin());
773 0 : j != i->includeConfig.end(); ++j)
774 : {
775 0 : rtl::OUString comp;
776 0 : if (getComponent(*j, &comp)) {
777 0 : comps[comp].includedPaths.insert(*j);
778 : }
779 0 : }
780 0 : for (strings_v::const_iterator j(i->excludeConfig.begin());
781 0 : j != i->excludeConfig.end(); ++j)
782 : {
783 0 : rtl::OUString comp;
784 0 : if (getComponent(*j, &comp)) {
785 0 : comps[comp].excludedPaths.insert(*j);
786 : }
787 0 : }
788 : }
789 :
790 : // check if the shared registrymodifications.xcu file exists
791 0 : bool bRegistryModificationsXcuExists = false;
792 0 : rtl::OUString regFilePath(m_aInfo.userdata);
793 0 : regFilePath += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/user/registrymodifications.xcu"));
794 0 : File regFile(regFilePath);
795 0 : ::osl::FileBase::RC nError = regFile.open(osl_File_OpenFlag_Read);
796 0 : if ( nError == ::osl::FileBase::E_None ) {
797 0 : bRegistryModificationsXcuExists = true;
798 0 : regFile.close();
799 : }
800 :
801 0 : for (Components::const_iterator i(comps.begin()); i != comps.end(); ++i) {
802 0 : if (!i->second.includedPaths.empty()) {
803 0 : if (!bRegistryModificationsXcuExists) {
804 : // shared registrymodifications.xcu does not exists
805 : // the configuration is split in many registry files
806 : // determine the file names from the first element in included paths
807 0 : rtl::OUStringBuffer buf(m_aInfo.userdata);
808 0 : buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("/user/registry/data"));
809 0 : sal_Int32 n = 0;
810 0 : do {
811 0 : rtl::OUString seg(i->first.getToken(0, '.', n));
812 : rtl::OUString enc(
813 : rtl::Uri::encode(
814 : seg, rtl_UriCharClassPchar, rtl_UriEncodeStrict,
815 0 : RTL_TEXTENCODING_UTF8));
816 0 : if (enc.isEmpty() && !seg.isEmpty()) {
817 : OSL_TRACE(
818 : ("configuration migration component %s ignored (cannot"
819 : " be encoded as file path)"),
820 : rtl::OUStringToOString(
821 : i->first, RTL_TEXTENCODING_UTF8).getStr());
822 : goto next;
823 : }
824 0 : buf.append(sal_Unicode('/'));
825 0 : buf.append(enc);
826 : } while (n >= 0);
827 0 : buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(".xcu"));
828 0 : regFilePath = buf.toString();
829 : }
830 : configuration::Update::get(
831 0 : comphelper::getProcessComponentContext())->
832 : insertModificationXcuFile(
833 0 : regFilePath, setToSeq(i->second.includedPaths),
834 0 : setToSeq(i->second.excludedPaths));
835 : } else {
836 : OSL_TRACE(
837 : ("configuration migration component %s ignored (only excludes,"
838 : " no includes)"),
839 : rtl::OUStringToOString(
840 : i->first, RTL_TEXTENCODING_UTF8).getStr());
841 : }
842 : next:;
843 0 : }
844 0 : }
845 :
846 : // removes elements of vector 2 in vector 1
847 0 : void MigrationImpl::subtract(strings_v& va, const strings_v& vb_c) const
848 : {
849 0 : strings_v vb(vb_c);
850 : // ensure uniqueness of entries
851 0 : sort(va.begin(), va.end());
852 0 : sort(vb.begin(), vb.end());
853 0 : unique(va.begin(), va.end());
854 0 : unique(vb.begin(), vb.end());
855 :
856 0 : strings_v::const_iterator i_ex = vb.begin();
857 0 : strings_v::iterator i_in;
858 0 : strings_v::iterator i_next;
859 0 : while (i_ex != vb.end())
860 : {
861 0 : i_in = va.begin();
862 0 : while (i_in != va.end())
863 : {
864 0 : if ( *i_in == *i_ex)
865 : {
866 0 : i_next = i_in+1;
867 0 : va.erase(i_in);
868 0 : i_in = i_next;
869 : // we can only find one match since we
870 : // ensured uniquness of the entries. ergo:
871 0 : break;
872 : }
873 : else
874 0 : ++i_in;
875 : }
876 0 : ++i_ex;
877 0 : }
878 0 : }
879 :
880 0 : uno::Reference< XNameAccess > MigrationImpl::getConfigAccess(const sal_Char* pPath, sal_Bool bUpdate)
881 : {
882 0 : uno::Reference< XNameAccess > xNameAccess;
883 : try{
884 0 : OUString sAccessSrvc;
885 0 : if (bUpdate)
886 0 : sAccessSrvc = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationUpdateAccess"));
887 : else
888 0 : sAccessSrvc = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess"));
889 :
890 0 : OUString sConfigURL = OUString::createFromAscii(pPath);
891 :
892 : uno::Reference< XMultiServiceFactory > theConfigProvider(
893 : configuration::theDefaultProvider::get(
894 0 : comphelper::getProcessComponentContext()));
895 :
896 : // access the provider
897 0 : uno::Sequence< uno::Any > theArgs(1);
898 0 : theArgs[ 0 ] <<= sConfigURL;
899 : xNameAccess = uno::Reference< XNameAccess > (
900 0 : theConfigProvider->createInstanceWithArguments(
901 0 : sAccessSrvc, theArgs ), uno::UNO_QUERY_THROW );
902 : }
903 0 : catch (const com::sun::star::uno::Exception& e)
904 : {
905 0 : OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
906 0 : OSL_FAIL(aMsg.getStr());
907 : }
908 0 : return xNameAccess;
909 : }
910 :
911 0 : void MigrationImpl::copyFiles()
912 : {
913 0 : strings_v::const_iterator i_file = m_vrFileList->begin();
914 0 : OUString localName;
915 0 : OUString destName;
916 0 : OUString userInstall;
917 : utl::Bootstrap::PathStatus aStatus;
918 0 : aStatus = utl::Bootstrap::locateUserInstallation(userInstall);
919 0 : if (aStatus == utl::Bootstrap::PATH_EXISTS)
920 : {
921 0 : while (i_file != m_vrFileList->end())
922 : {
923 : // remove installation prefix from file
924 0 : localName = i_file->copy(m_aInfo.userdata.getLength());
925 0 : if (localName.endsWith( "/autocorr/acor_.dat"))
926 : {
927 : // Previous versions used an empty language tag for
928 : // LANGUAGE_DONTKNOW with the "[All]" autocorrection entry.
929 : // As of LibreOffice 4.0 it is 'und' for LANGUAGE_UNDETERMINED
930 : // so the file name is "acor_und.dat".
931 0 : localName = localName.copy( 0, localName.getLength() - 4) + "und.dat";
932 : }
933 0 : destName = userInstall + localName;
934 0 : INetURLObject aURL(destName);
935 : // check whether destination directory exists
936 0 : aURL.removeSegment();
937 0 : _checkAndCreateDirectory(aURL);
938 0 : FileBase::RC copyResult = File::copy(*i_file, destName);
939 0 : if (copyResult != FileBase::E_None)
940 : {
941 0 : OString msg("Cannot copy ");
942 0 : msg += OUStringToOString(*i_file, RTL_TEXTENCODING_UTF8) + " to "
943 0 : + OUStringToOString(destName, RTL_TEXTENCODING_UTF8);
944 0 : OSL_FAIL(msg.getStr());
945 : }
946 0 : ++i_file;
947 0 : }
948 : }
949 : else
950 : {
951 : OSL_FAIL("copyFiles: UserInstall does not exist");
952 0 : }
953 0 : }
954 :
955 0 : void MigrationImpl::runServices()
956 : {
957 : // Build argument array
958 0 : uno::Sequence< uno::Any > seqArguments(3);
959 0 : seqArguments[0] = uno::makeAny(NamedValue(
960 : OUString(RTL_CONSTASCII_USTRINGPARAM("Productname")),
961 0 : uno::makeAny(m_aInfo.productname)));
962 0 : seqArguments[1] = uno::makeAny(NamedValue(
963 : OUString(RTL_CONSTASCII_USTRINGPARAM("UserData")),
964 0 : uno::makeAny(m_aInfo.userdata)));
965 :
966 :
967 : // create an instance of every migration service
968 : // and execute the migration job
969 0 : uno::Reference< XJob > xMigrationJob;
970 :
971 0 : migrations_v::const_iterator i_mig = m_vrMigrations->begin();
972 0 : while (i_mig != m_vrMigrations->end())
973 : {
974 0 : if( !i_mig->service.isEmpty())
975 : {
976 :
977 : try
978 : {
979 : // set black list for extension migration
980 0 : uno::Sequence< rtl::OUString > seqExtBlackList;
981 0 : sal_uInt32 nSize = i_mig->excludeExtensions.size();
982 0 : if ( nSize > 0 )
983 : seqExtBlackList = comphelper::arrayToSequence< ::rtl::OUString >(
984 0 : &i_mig->excludeExtensions[0], nSize );
985 0 : seqArguments[2] = uno::makeAny(NamedValue(
986 : OUString(RTL_CONSTASCII_USTRINGPARAM("ExtensionBlackList")),
987 0 : uno::makeAny( seqExtBlackList )));
988 :
989 0 : xMigrationJob = uno::Reference< XJob >(m_xFactory->createInstanceWithArguments(
990 0 : i_mig->service, seqArguments), uno::UNO_QUERY_THROW);
991 :
992 0 : xMigrationJob->execute(uno::Sequence< NamedValue >());
993 :
994 :
995 : }
996 0 : catch (const Exception& e)
997 : {
998 0 : OString aMsg("Execution of migration service failed (Exception caught).\nService: ");
999 0 : aMsg += OUStringToOString(i_mig->service, RTL_TEXTENCODING_ASCII_US) + "\nMessage: ";
1000 0 : aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
1001 0 : OSL_FAIL(aMsg.getStr());
1002 : }
1003 0 : catch (...)
1004 : {
1005 0 : OString aMsg("Execution of migration service failed (Exception caught).\nService: ");
1006 0 : aMsg += OUStringToOString(i_mig->service, RTL_TEXTENCODING_ASCII_US) +
1007 0 : "\nNo message available";
1008 0 : OSL_FAIL(aMsg.getStr());
1009 : }
1010 :
1011 : }
1012 0 : ++i_mig;
1013 0 : }
1014 0 : }
1015 :
1016 0 : ::std::vector< MigrationModuleInfo > MigrationImpl::dectectUIChangesForAllModules() const
1017 : {
1018 0 : ::std::vector< MigrationModuleInfo > vModulesInfo;
1019 0 : const ::rtl::OUString MENUBAR(RTL_CONSTASCII_USTRINGPARAM("menubar"));
1020 0 : const ::rtl::OUString TOOLBAR(RTL_CONSTASCII_USTRINGPARAM("toolbar"));
1021 :
1022 0 : uno::Sequence< uno::Any > lArgs(2);
1023 0 : lArgs[0] <<= m_aInfo.userdata + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/user/config/soffice.cfg/modules"));
1024 0 : lArgs[1] <<= embed::ElementModes::READ;
1025 :
1026 : uno::Reference< lang::XSingleServiceFactory > xStorageFactory(
1027 0 : embed::FileSystemStorageFactory::create(comphelper::getComponentContext(m_xFactory)));
1028 0 : uno::Reference< embed::XStorage > xModules;
1029 :
1030 0 : xModules = uno::Reference< embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY);
1031 0 : if (!xModules.is())
1032 : return vModulesInfo;
1033 :
1034 0 : uno::Reference< container::XNameAccess > xAccess = uno::Reference< container::XNameAccess >(xModules, uno::UNO_QUERY);
1035 0 : uno::Sequence< ::rtl::OUString > lNames = xAccess->getElementNames();
1036 0 : sal_Int32 nLength = lNames.getLength();
1037 0 : for (sal_Int32 i=0; i<nLength; ++i)
1038 : {
1039 0 : ::rtl::OUString sModuleShortName = lNames[i];
1040 0 : uno::Reference< embed::XStorage > xModule = xModules->openStorageElement(sModuleShortName, embed::ElementModes::READ);
1041 0 : if (xModule.is())
1042 : {
1043 0 : MigrationModuleInfo aModuleInfo;
1044 :
1045 0 : uno::Reference< embed::XStorage > xMenubar = xModule->openStorageElement(MENUBAR, embed::ElementModes::READ);
1046 0 : if (xMenubar.is())
1047 : {
1048 0 : uno::Reference< container::XNameAccess > xNameAccess = uno::Reference< container::XNameAccess >(xMenubar, uno::UNO_QUERY);
1049 0 : if (xNameAccess->getElementNames().getLength() > 0)
1050 : {
1051 0 : aModuleInfo.sModuleShortName = sModuleShortName;
1052 0 : aModuleInfo.bHasMenubar = sal_True;
1053 0 : }
1054 : }
1055 :
1056 0 : uno::Reference< embed::XStorage > xToolbar = xModule->openStorageElement(TOOLBAR, embed::ElementModes::READ);
1057 0 : if (xToolbar.is())
1058 : {
1059 0 : const ::rtl::OUString RESOURCEURL_CUSTOM_ELEMENT(RTL_CONSTASCII_USTRINGPARAM("custom_"));
1060 0 : sal_Int32 nCustomLen = 7;
1061 :
1062 0 : uno::Reference< container::XNameAccess > xNameAccess = uno::Reference< container::XNameAccess >(xToolbar, uno::UNO_QUERY);
1063 0 : ::uno::Sequence< ::rtl::OUString > lToolbars = xNameAccess->getElementNames();
1064 0 : for (sal_Int32 j=0; j<lToolbars.getLength(); ++j)
1065 : {
1066 0 : ::rtl::OUString sToolbarName = lToolbars[j];
1067 0 : if (sToolbarName.getLength()>=nCustomLen &&
1068 0 : sToolbarName.copy(0, nCustomLen).equals(RESOURCEURL_CUSTOM_ELEMENT))
1069 0 : continue;
1070 :
1071 0 : aModuleInfo.sModuleShortName = sModuleShortName;
1072 0 : sal_Int32 nIndex = sToolbarName.lastIndexOf('.');
1073 0 : if (nIndex > 0)
1074 : {
1075 0 : ::rtl::OUString sExtension(sToolbarName.copy(nIndex));
1076 0 : ::rtl::OUString sToolbarResourceName(sToolbarName.copy(0, nIndex));
1077 0 : if (!sToolbarResourceName.isEmpty() && sExtension.equalsAsciiL(".xml", 4))
1078 0 : aModuleInfo.m_vToolbars.push_back(sToolbarResourceName);
1079 : }
1080 0 : }
1081 : }
1082 :
1083 0 : if (!aModuleInfo.sModuleShortName.isEmpty())
1084 0 : vModulesInfo.push_back(aModuleInfo);
1085 : }
1086 0 : }
1087 :
1088 0 : return vModulesInfo;
1089 : }
1090 :
1091 0 : void MigrationImpl::compareOldAndNewConfig(const ::rtl::OUString& sParent,
1092 : const uno::Reference< container::XIndexContainer >& xIndexOld,
1093 : const uno::Reference< container::XIndexContainer >& xIndexNew,
1094 : const ::rtl::OUString& sResourceURL)
1095 : {
1096 0 : const ::rtl::OUString MENU_SEPERATOR(RTL_CONSTASCII_USTRINGPARAM(" | "));
1097 :
1098 0 : ::std::vector< MigrationItem > vOldItems;
1099 0 : ::std::vector< MigrationItem > vNewItems;
1100 0 : uno::Sequence< beans::PropertyValue > aProp;
1101 0 : sal_Int32 nOldCount = xIndexOld->getCount();
1102 0 : sal_Int32 nNewCount = xIndexNew->getCount();
1103 :
1104 0 : for (int n=0; n<nOldCount; ++n)
1105 : {
1106 0 : MigrationItem aMigrationItem;
1107 0 : if (xIndexOld->getByIndex(n) >>= aProp)
1108 : {
1109 0 : for(int i=0; i<aProp.getLength(); ++i)
1110 : {
1111 0 : if ( aProp[i].Name == ITEM_DESCRIPTOR_COMMANDURL )
1112 0 : aProp[i].Value >>= aMigrationItem.m_sCommandURL;
1113 0 : else if ( aProp[i].Name == ITEM_DESCRIPTOR_CONTAINER )
1114 0 : aProp[i].Value >>= aMigrationItem.m_xPopupMenu;
1115 : }
1116 :
1117 0 : if (!aMigrationItem.m_sCommandURL.isEmpty())
1118 0 : vOldItems.push_back(aMigrationItem);
1119 : }
1120 0 : }
1121 :
1122 0 : for (int n=0; n<nNewCount; ++n)
1123 : {
1124 0 : MigrationItem aMigrationItem;
1125 0 : if (xIndexNew->getByIndex(n) >>= aProp)
1126 : {
1127 0 : for(int i=0; i<aProp.getLength(); ++i)
1128 : {
1129 0 : if ( aProp[i].Name == ITEM_DESCRIPTOR_COMMANDURL )
1130 0 : aProp[i].Value >>= aMigrationItem.m_sCommandURL;
1131 0 : else if ( aProp[i].Name == ITEM_DESCRIPTOR_CONTAINER )
1132 0 : aProp[i].Value >>= aMigrationItem.m_xPopupMenu;
1133 : }
1134 :
1135 0 : if (!aMigrationItem.m_sCommandURL.isEmpty())
1136 0 : vNewItems.push_back(aMigrationItem);
1137 : }
1138 0 : }
1139 :
1140 0 : ::std::vector< MigrationItem >::iterator it;
1141 :
1142 0 : ::rtl::OUString sSibling;
1143 0 : for (it = vOldItems.begin(); it!=vOldItems.end(); ++it)
1144 : {
1145 0 : ::std::vector< MigrationItem >::iterator pFound = ::std::find(vNewItems.begin(), vNewItems.end(), *it);
1146 0 : if (pFound != vNewItems.end() && it->m_xPopupMenu.is())
1147 : {
1148 0 : ::rtl::OUString sName;
1149 0 : if (!sParent.isEmpty())
1150 0 : sName = sParent + MENU_SEPERATOR + it->m_sCommandURL;
1151 : else
1152 0 : sName = it->m_sCommandURL;
1153 0 : compareOldAndNewConfig(sName, it->m_xPopupMenu, pFound->m_xPopupMenu, sResourceURL);
1154 : }
1155 0 : else if (pFound == vNewItems.end())
1156 : {
1157 0 : MigrationItem aMigrationItem(sParent, sSibling, it->m_sCommandURL, it->m_xPopupMenu);
1158 0 : if (m_aOldVersionItemsHashMap.find(sResourceURL)==m_aOldVersionItemsHashMap.end())
1159 : {
1160 0 : ::std::vector< MigrationItem > vMigrationItems;
1161 0 : m_aOldVersionItemsHashMap.insert(MigrationHashMap::value_type(sResourceURL, vMigrationItems));
1162 0 : m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1163 : }
1164 : else
1165 : {
1166 0 : if (::std::find(m_aOldVersionItemsHashMap[sResourceURL].begin(), m_aOldVersionItemsHashMap[sResourceURL].end(), aMigrationItem)==m_aOldVersionItemsHashMap[sResourceURL].end())
1167 0 : m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1168 0 : }
1169 : }
1170 :
1171 0 : sSibling = it->m_sCommandURL;
1172 : }
1173 :
1174 0 : uno::Reference< container::XIndexContainer > xPopup;
1175 0 : for (it = vNewItems.begin(); it!=vNewItems.end(); ++it)
1176 : {
1177 0 : ::std::vector< MigrationItem >::iterator pFound = ::std::find(vOldItems.begin(), vOldItems.end(), *it);
1178 0 : if (pFound != vOldItems.end() && it->m_xPopupMenu.is())
1179 : {
1180 0 : ::rtl::OUString sName;
1181 0 : if (!sParent.isEmpty())
1182 0 : sName = sParent + MENU_SEPERATOR + it->m_sCommandURL;
1183 : else
1184 0 : sName = it->m_sCommandURL;
1185 0 : compareOldAndNewConfig(sName, pFound->m_xPopupMenu, it->m_xPopupMenu, sResourceURL);
1186 : }
1187 0 : else if (::std::find(vOldItems.begin(), vOldItems.end(), *it) == vOldItems.end())
1188 : {
1189 0 : MigrationItem aMigrationItem(sParent, sSibling, it->m_sCommandURL, it->m_xPopupMenu);
1190 0 : if (m_aNewVersionItemsHashMap.find(sResourceURL)==m_aNewVersionItemsHashMap.end())
1191 : {
1192 0 : ::std::vector< MigrationItem > vMigrationItems;
1193 0 : m_aNewVersionItemsHashMap.insert(MigrationHashMap::value_type(sResourceURL, vMigrationItems));
1194 0 : m_aNewVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1195 : }
1196 : else
1197 : {
1198 0 : if (::std::find(m_aNewVersionItemsHashMap[sResourceURL].begin(), m_aNewVersionItemsHashMap[sResourceURL].end(), aMigrationItem)==m_aNewVersionItemsHashMap[sResourceURL].end())
1199 0 : m_aNewVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1200 0 : }
1201 : }
1202 0 : }
1203 0 : }
1204 :
1205 0 : void MigrationImpl::mergeOldToNewVersion(const uno::Reference< ui::XUIConfigurationManager >& xCfgManager,
1206 : const uno::Reference< container::XIndexContainer>& xIndexContainer,
1207 : const ::rtl::OUString& sModuleIdentifier,
1208 : const ::rtl::OUString& sResourceURL)
1209 : {
1210 0 : MigrationHashMap::iterator pFound = m_aOldVersionItemsHashMap.find(sResourceURL);
1211 0 : if (pFound==m_aOldVersionItemsHashMap.end())
1212 0 : return;
1213 :
1214 0 : ::std::vector< MigrationItem >::iterator it;
1215 0 : for (it=pFound->second.begin(); it!=pFound->second.end(); ++it)
1216 : {
1217 0 : uno::Reference< container::XIndexContainer > xTemp = xIndexContainer;
1218 :
1219 0 : ::rtl::OUString sParentNodeName = it->m_sParentNodeName;
1220 0 : sal_Int32 nIndex = 0;
1221 0 : do
1222 : {
1223 0 : ::rtl::OUString sToken = sParentNodeName.getToken(0, '|', nIndex).trim();
1224 0 : if (sToken.isEmpty())
1225 : break;
1226 :
1227 0 : sal_Int32 nCount = xTemp->getCount();
1228 0 : for (sal_Int32 i=0; i<nCount; ++i)
1229 : {
1230 0 : ::rtl::OUString sCommandURL;
1231 0 : ::rtl::OUString sLabel;
1232 0 : uno::Reference< container::XIndexContainer > xChild;
1233 :
1234 0 : uno::Sequence< beans::PropertyValue > aPropSeq;
1235 0 : xTemp->getByIndex(i) >>= aPropSeq;
1236 0 : for (sal_Int32 j=0; j<aPropSeq.getLength(); ++j)
1237 : {
1238 0 : ::rtl::OUString sPropName = aPropSeq[j].Name;
1239 0 : if ( sPropName == ITEM_DESCRIPTOR_COMMANDURL )
1240 0 : aPropSeq[j].Value >>= sCommandURL;
1241 0 : else if ( sPropName == ITEM_DESCRIPTOR_LABEL )
1242 0 : aPropSeq[j].Value >>= sLabel;
1243 0 : else if ( sPropName == ITEM_DESCRIPTOR_CONTAINER )
1244 0 : aPropSeq[j].Value >>= xChild;
1245 0 : }
1246 :
1247 0 : if (sCommandURL == sToken)
1248 : {
1249 0 : xTemp = xChild;
1250 : break;
1251 : }
1252 0 : }
1253 :
1254 : } while (nIndex>=0);
1255 :
1256 0 : if (nIndex == -1)
1257 : {
1258 0 : uno::Sequence< beans::PropertyValue > aPropSeq(3);
1259 :
1260 0 : aPropSeq[0].Name = rtl::OUString(ITEM_DESCRIPTOR_COMMANDURL);
1261 0 : aPropSeq[0].Value <<= it->m_sCommandURL;
1262 0 : aPropSeq[1].Name = rtl::OUString(ITEM_DESCRIPTOR_LABEL);
1263 0 : aPropSeq[1].Value <<= retrieveLabelFromCommand(it->m_sCommandURL, sModuleIdentifier);
1264 0 : aPropSeq[2].Name = rtl::OUString(ITEM_DESCRIPTOR_CONTAINER);
1265 0 : aPropSeq[2].Value <<= it->m_xPopupMenu;
1266 :
1267 0 : if (it->m_sPrevSibling.isEmpty())
1268 0 : xTemp->insertByIndex(0, uno::makeAny(aPropSeq));
1269 0 : else if (!it->m_sPrevSibling.isEmpty())
1270 : {
1271 0 : sal_Int32 nCount = xTemp->getCount();
1272 0 : sal_Int32 i = 0;
1273 0 : for (; i<nCount; ++i)
1274 : {
1275 0 : ::rtl::OUString sCmd;
1276 0 : uno::Sequence< beans::PropertyValue > aTempPropSeq;
1277 0 : xTemp->getByIndex(i) >>= aTempPropSeq;
1278 0 : for (sal_Int32 j=0; j<aTempPropSeq.getLength(); ++j)
1279 : {
1280 0 : if ( aTempPropSeq[j].Name == ITEM_DESCRIPTOR_COMMANDURL )
1281 : {
1282 0 : aTempPropSeq[j].Value >>= sCmd;
1283 0 : break;
1284 : }
1285 : }
1286 :
1287 0 : if (sCmd.equals(it->m_sPrevSibling))
1288 : break;
1289 0 : }
1290 :
1291 0 : xTemp->insertByIndex(i+1, uno::makeAny(aPropSeq));
1292 0 : }
1293 : }
1294 0 : }
1295 :
1296 0 : uno::Reference< container::XIndexAccess > xIndexAccess(xIndexContainer, uno::UNO_QUERY);
1297 0 : if (xIndexAccess.is())
1298 0 : xCfgManager->replaceSettings(sResourceURL, xIndexAccess);
1299 :
1300 0 : uno::Reference< ui::XUIConfigurationPersistence > xUIConfigurationPersistence(xCfgManager, uno::UNO_QUERY);
1301 0 : if (xUIConfigurationPersistence.is())
1302 0 : xUIConfigurationPersistence->store();
1303 : }
1304 :
1305 0 : uno::Reference< ui::XUIConfigurationManager > NewVersionUIInfo::getConfigManager(const ::rtl::OUString& sModuleShortName) const
1306 : {
1307 0 : uno::Reference< ui::XUIConfigurationManager > xCfgManager;
1308 :
1309 0 : for (sal_Int32 i=0; i<m_lCfgManagerSeq.getLength(); ++i)
1310 : {
1311 0 : if (m_lCfgManagerSeq[i].Name.equals(sModuleShortName))
1312 : {
1313 0 : m_lCfgManagerSeq[i].Value >>= xCfgManager;
1314 0 : break;
1315 : }
1316 : }
1317 :
1318 0 : return xCfgManager;
1319 : }
1320 :
1321 0 : uno::Reference< container::XIndexContainer > NewVersionUIInfo::getNewMenubarSettings(const ::rtl::OUString& sModuleShortName) const
1322 : {
1323 0 : uno::Reference< container::XIndexContainer > xNewMenuSettings;
1324 :
1325 0 : for (sal_Int32 i=0; i<m_lNewVersionMenubarSettingsSeq.getLength(); ++i)
1326 : {
1327 0 : if (m_lNewVersionMenubarSettingsSeq[i].Name.equals(sModuleShortName))
1328 : {
1329 0 : m_lNewVersionMenubarSettingsSeq[i].Value >>= xNewMenuSettings;
1330 0 : break;
1331 : }
1332 : }
1333 :
1334 0 : return xNewMenuSettings;
1335 : }
1336 :
1337 0 : uno::Reference< container::XIndexContainer > NewVersionUIInfo::getNewToolbarSettings(const ::rtl::OUString& sModuleShortName, const ::rtl::OUString& sToolbarName) const
1338 : {
1339 0 : uno::Reference< container::XIndexContainer > xNewToolbarSettings;
1340 :
1341 0 : for (sal_Int32 i=0; i<m_lNewVersionToolbarSettingsSeq.getLength(); ++i)
1342 : {
1343 0 : if (m_lNewVersionToolbarSettingsSeq[i].Name.equals(sModuleShortName))
1344 : {
1345 0 : uno::Sequence< beans::PropertyValue > lToolbarSettingsSeq;
1346 0 : m_lNewVersionToolbarSettingsSeq[i].Value >>= lToolbarSettingsSeq;
1347 0 : for (sal_Int32 j=0; j<lToolbarSettingsSeq.getLength(); ++j)
1348 : {
1349 0 : if (lToolbarSettingsSeq[j].Name.equals(sToolbarName))
1350 : {
1351 0 : lToolbarSettingsSeq[j].Value >>= xNewToolbarSettings;
1352 0 : break;
1353 : }
1354 : }
1355 :
1356 0 : break;
1357 : }
1358 : }
1359 :
1360 0 : return xNewToolbarSettings;
1361 : }
1362 :
1363 0 : void NewVersionUIInfo::init(const ::std::vector< MigrationModuleInfo >& vModulesInfo)
1364 : {
1365 0 : m_lCfgManagerSeq.realloc(vModulesInfo.size());
1366 0 : m_lNewVersionMenubarSettingsSeq.realloc(vModulesInfo.size());
1367 0 : m_lNewVersionToolbarSettingsSeq.realloc(vModulesInfo.size());
1368 :
1369 0 : const ::rtl::OUString sMenubarResourceURL(RTL_CONSTASCII_USTRINGPARAM("private:resource/menubar/menubar"));
1370 0 : const ::rtl::OUString sToolbarResourcePre(RTL_CONSTASCII_USTRINGPARAM("private:resource/toolbar/"));
1371 :
1372 0 : uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier = ui::ModuleUIConfigurationManagerSupplier::create( ::comphelper::getProcessComponentContext() );
1373 :
1374 0 : for (sal_uInt32 i=0; i<vModulesInfo.size(); ++i)
1375 : {
1376 0 : ::rtl::OUString sModuleIdentifier = mapModuleShortNameToIdentifier(vModulesInfo[i].sModuleShortName);
1377 0 : if (!sModuleIdentifier.isEmpty())
1378 : {
1379 0 : uno::Reference< ui::XUIConfigurationManager > xCfgManager = xModuleCfgSupplier->getUIConfigurationManager(sModuleIdentifier);
1380 0 : m_lCfgManagerSeq[i].Name = vModulesInfo[i].sModuleShortName;
1381 0 : m_lCfgManagerSeq[i].Value <<= xCfgManager;
1382 :
1383 0 : if (vModulesInfo[i].bHasMenubar)
1384 : {
1385 0 : m_lNewVersionMenubarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName;
1386 0 : m_lNewVersionMenubarSettingsSeq[i].Value <<= xCfgManager->getSettings(sMenubarResourceURL, sal_True);
1387 : }
1388 :
1389 0 : sal_Int32 nToolbars = vModulesInfo[i].m_vToolbars.size();
1390 0 : if (nToolbars > 0)
1391 : {
1392 0 : uno::Sequence< beans::PropertyValue > lPropSeq(nToolbars);
1393 0 : for (sal_Int32 j=0; j<nToolbars; ++j)
1394 : {
1395 0 : ::rtl::OUString sToolbarName = vModulesInfo[i].m_vToolbars[j];
1396 0 : ::rtl::OUString sToolbarResourceURL = sToolbarResourcePre + sToolbarName;
1397 :
1398 0 : lPropSeq[j].Name = sToolbarName;
1399 0 : lPropSeq[j].Value <<= xCfgManager->getSettings(sToolbarResourceURL, sal_True);
1400 0 : }
1401 :
1402 0 : m_lNewVersionToolbarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName;
1403 0 : m_lNewVersionToolbarSettingsSeq[i].Value <<= lPropSeq;
1404 0 : }
1405 : }
1406 0 : }
1407 0 : }
1408 :
1409 : } // namespace desktop
1410 :
1411 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|